home *** CD-ROM | disk | FTP | other *** search
- Date: Wed, 13 Jan 88 04:26 PST
- From: <MULTI%TRIUMFCL.BITNET@CUNYVM.CUNY.EDU>
- Subject: BIOS.ASM update INFO-IBMPC librarys
- To: hicks@walker-emh.arpa
-
- Page 80,132
- Title BIOS - For Intel 8088 or NEC "V20" turbo motherboards. Use MASM 4.0
- ;
- ; This bios will work on IBM-PC/xt and many other compatibles that share a
- ; similar design concept. You do not need to have a turbo motherboard to
- ; use this bios, but if you do, then use the following key sequence
- ; CTRL ALT -
- ; to toggle the computer speed between fast and slow (=IBM compatible)
- ;
- ; This BIOS can produce the following error messages at IPL time
- ;
- ER_BIOS equ 01h ; Bad ROM bios checksum, patch last byte
- ER_RAM equ 02h ; Bad RAM in main memory, replace
- ER_CRT equ 04h ; Bad RAM in video card, replace
- ER_MEM equ 10h ; Bad RAM in vector area, replace
- ER_ROM equ 20h ; Bad ROM in expansion area, bad checksum
- ;
- ; The last two bytes have to be patched with DEBUG as follows
- ;
- ; FFFF 00.xx ( avoid ER_BIOS on bootstrap ) --------------------
- ; FFFE 00.FE ( leaves IBM-PC/xt signature ) ----------------- |
- ; | |
- ; where "xx" results in a zero checksum for the whole BIOS rom, for ex | |
- ; | |
- ; masm BIOS; ( Assemble BIOS source code) | |
- ; link BIOS; ( Link the BIOS object code) | |
- ; debug BIOS.EXE ( Exe2bin BIOS binary code) | |
- ; -nBIOS.BIN ( Name of the output binary) | |
- ; -eCS:FFFE ( Opens BIOS signature byte) | |
- ; .FE ( Leave IBM-PC/xt signature) <-- |
- ; -eCS:FFFF ( Opens BIOS checksum byte) |
- ;; -------> .DC ( Force ROM checksum = zero) <-----
- ;; -rBX ( Opens hi order byte count)
- ;; :0 ( ... must be 0 bytes long)
- ;; -rCX ( Opens lo order byte count)
- ;; :2000 ( ... BIOS 2000 bytes long)
- ;; -wCS:E000 ( Output to BIOS.BIN file)
- ;; -q
- ;;
- ;; You must correct the checksum by manually patching the last byte so as the
- ;; the entire 2764-2 eprom sums to zero. I wish DEBUG could checksum blocks.
- ;
- ; ************************Miscellaneous definitions************************
- ; *
- MAX_MEMORY =704 ; Maximum kilobytes of memory allowed *
- ;SLOW_FLOPPY =1 ; Define to run floppy always at 4.77 mHz *
- ; *
- ; ************************Miscellaneous definitions************************
- ;
- entry macro x
- pad =BANNER - $ + x - 0E000h
- if pad LT 0
- .err
- %out 'No room for ENTRY point'
- endif
- if pad GT 0
- db pad DUP(0FFh)
- endif
- endm
- ;
- jmpf macro x,y
- db 0EAh;
- dw y,x
- endm
- ;
- retf macro x
- ifb <x>
- db 0CBh
- else
- db 0CAh
- dw x
- endif
- endm
- ;
- LF equ 0Ah
- CR equ 0Dh
- ;
- .SALL ; Suppress Macro Expansions
- .LFCOND ; List False Conditionals
- ;
- ASSUME DS:code, SS:code, CS:code, ES:code
- data SEGMENT at 40h ; IBM compatible data structure
- dw 4 dup(?) ; 40:00 ; RS232 com. ports - up to four
- dw 4 dup(?) ; 40:08 ; Printer ports - up to four
- dw ? ; 40:10 ; Equipment present word
- ; + (1 iff floppies) * 1.
- ; + (# 64K sys ram ) * 4.
- ; + (init crt mode ) * 16.
- ; + (# of floppies ) * 64.
- ; + (# serial ports) * 512.
- ; + (1 iff toy port) * 4096.
- ; + (# parallel LPT) * 16384.
- db ? ; 40:12 ; MFG test flags, unused by us
- dw ? ; 40:13 ; Memory size, kilobytes
- db ? ; 40:15 ; IPL errors<-table/scratchpad
- db ? ; ...unused
- ;---------------[Keyboard data area]------------;
- db ?,? ; 40:17 ; Shift/Alt/etc. keyboard flags
- db ? ; 40:19 ; Alt-KEYPAD char. goes here
- dw ? ; 40:1A ; --> keyboard buffer head
- dw ? ; 40:1C ; --> keyboard buffer tail
- dw 16 dup(?) ; 40:1E ; Keyboard Buffer (Scan,Value)
- ;---------------[Diskette data area]------------;
- db ? ; 40:3E ; Drive Calibration bits 0 - 3
- db ? ; 40:3F ; Drive Motor(s) on 0-3,7=write
- db ? ; 40:40 ; Ticks (18/sec) til motor off
- db ? ; 40:41 ; Floppy return code stat byte
- ; 1 = bad ic 765 command req.
- ; 2 = address mark not found
- ; 3 = write to protected disk
- ; 4 = sector not found
- ; 8 = data late (DMA overrun)
- ; 9 = DMA failed 64K page end
- ; 16 = bad CRC on floppy read
- ; 32 = bad NEC 765 controller
- ; 64 = seek operation failed
- ;128 = disk drive timed out
- db 7 dup(?) ; 40:42 ; Status bytes from NEC 765
- ;---------------[Video display area]------------;
- db ? ; 40:49 ; Current CRT mode (software)
- ; 0 = 40 x 25 text (no color)
- ; 1 = 40 x 25 text (16 color)
- ; 2 = 80 x 25 text (no color)
- ; 3 = 80 x 25 text (16 color)
- ; 4 = 320 x 200 grafix 4 color
- ; 5 = 320 x 200 grafix 0 color
- ; 6 = 640 x 200 grafix 0 color
- ; 7 = 80 x 25 text (mono card)
- dw ? ; 40:4A ; Columns on CRT screen
- dw ? ; 40:4C ; Bytes in the regen region
- dw ? ; 40:4E ; Byte offset in regen region
- dw 8 dup(?) ; 40:50 ; Cursor pos for up to 8 pages
- dw ? ; 40:60 ; Current cursor mode setting
- db ? ; 40:62 ; Current page on display
- dw ? ; 40:63 ; Base addres (B000h or B800h)
- db ? ; 40:65 ; ic 6845 mode reg. (hardware)
- db ? ; 40:66 ; Current CGA palette
- ;---------------[Used to setup ROM]-------------;
- dw ?,? ; 40:67 ; Eprom base Offset,Segment
- db ? ; 40:6B ; Last spurious interrupt IRQ
- ;---------------[Timer data area]---------------;
- dw ? ; 40:6C ; Ticks since midnite (lo)
- dw ? ; 40:6E ; Ticks since midnite (hi)
- db ? ; 40:70 ; Non-zero if new day
- ;---------------[System data area]--------------;
- db ? ; 40:71 ; Sign bit set iff break
- dw ? ; 40:72 ; Warm boot iff 1234h value
- ;---------------[Hard disk scratchpad]----------;
- dw ?,? ; 40:74 ;
- ;---------------[Timout areas/PRT/LPT]----------;
- db 4 dup(?) ; 40:78 ; Ticks for LPT 1-4 timeouts
- db 4 dup(?) ; 40:7C ; Ticks for COM 1-4 timeouts
- ;---------------[Keyboard buf start/nd]---------;
- dw ? ; 40:80 ; Contains 1Eh, buffer start
- dw ? ; 40:82 ; Contains 3Eh, buffer end
- data ENDS
-
- dosdir SEGMENT at 50h ; Boot disk directory from IPL
- xerox label byte ; 0 if Print Screen idle
- ; 1 if PrtSc xeroxing screen
- ;255 if PrtSc error in xerox
- ; ...non-grafix PrtSc in bios
- db 200h dup(?) ; PC-DOS bootstrap procedure
- ; ...IBMBIO.COM buffers the
- ; ...directory of the boot
- ; ...device here at IPL time
- ; ...when locating the guts
- ; ...of the operating system
- ; ...filename "IBMDOS.COM"
- dosdir ends
-
- dosseg SEGMENT at 70h ; "Kernel" of PC-DOS op sys
- ;IBMBIO.COM file loaded by boot block. Device Drivers/Bootstrap. CONTIGUOUS<---
- ;IBMDOS.COM operating system nucleus immediately follows IBMBIO.COM and |
- ; doesn`t have to be contiguous. The IBMDOS operating system nucleus |
- ; binary image is loaded by transient code in IBMBIO binary image |
- dosseg ends ; |
- iplseg SEGMENT at 0h ; Segment for boot block |
- ;The following boot block is loaded with 512. bytes on the first sector of |
- ;the bootable device by code resident in the ROM-resident bios. Control is |
- ;then transferred to the first word 0000:7C00 of the disk-resident bootstrap |
- ORG 07C00h ; ..offset for boot block |
- boot db 200h dup(?) ; ..start disk resident boot--
- iplseg ends
-
- code SEGMENT
- ORG 0E000h
-
- BANNER db ' Generic Turbo XT Bios 1987',CR,LF
- db ' for 8088 or V20 cpu',CR,LF
- db ' (c)Anonymous',CR,LF
- db LF,0
-
- LPTRS dw 03BCh,0378h,0278h ; Possible line printer ports
-
- ENTRY 0E05Bh ; IBM restart entry point
-
- COLD: MOV AX,40h ; Entered by POWER_ON/RESET
- MOV DS,AX
- MOV Word ptr DS:72h,0 ; Show data areas not init
-
- WARM: CLI ; Begin FLAG test of CPU
- XOR AX,AX
- JB HALT
- JO HALT
- JS HALT
- JNZ HALT
- JPO HALT
- ADD AX,1
- JZ HALT
- JPE HALT
- SUB AX,8002h
- JS HALT
- INC AX
- JNO HALT
- SHL AX,1
- JNB HALT
- JNZ HALT
- SHL AX,1
- JB HALT
-
- MOV BX,0101010101010101b ; Begin REGISTER test of CPU
- CPUTST: MOV BP,BX
- MOV CX,BP
- MOV SP,CX
- MOV DX,SP
- MOV SS,DX
- MOV SI,SS
- MOV ES,SI
- MOV DI,ES
- MOV DS,DI
- MOV AX,DS
- CMP AX,0101010101010101b
- JNZ CPU1
- NOT AX
- MOV BX,AX
- JMP CPUTST
-
- CPU1: XOR AX,1010101010101010b
- JZ CPU_OK
-
- HALT: HLT
-
- CPU_OK: CLD
- MOV AL,0 ; Prepare to initialize
- OUT 0A0h,AL ; ...no NMI interrupts
- MOV DX,3D8h ; Load Color Graphic port
- OUT DX,AL ; ...no video display
- MOV DX,3B8h ; Load Monochrome port
- INC AL ; ...no video display
- OUT DX,AL ; ...write it out
- MOV AL,10011001b ; Program 8255 PIA chip
- OUT 63h,AL ; ...Ports A & C, inputs
- MOV AL,10100101b ; Set (non)turbo mode
- OUT 61h,AL ; ...on main board
-
- MOV AL,01010100b ; ic 8253 inits memory refresh
- OUT 43h,AL ; ...chan 1 pulses ic 8237 to
- MOV AL,12h ; ...dma every 12h clock ticks
- OUT 41h,AL ; ...64K done in 1 millisecond
- MOV AL,01000000b ; Latch value 12h in 8253 clock
- OUT 43h,AL ; ...chip channel 1 counter
-
- IC8237: MOV AL,0 ; Do some initialization
- OUT 81h,AL ; ...dma page reg, chan 2
- OUT 82h,AL ; ...dma page reg, chan 3
- OUT 83h,AL ; ...dma page reg, chan 0,1
- OUT 0Dh,AL ; Stop DMA on 8237 chip
- MOV AL,01011000b ; Refresh auto-init dummy read
- OUT 0Bh,AL ; ...on channel 0 of DMA chip
- MOV AL,01000001b ; Block verify
- OUT 0Bh,AL ; ...on channel 1 of DMA chip
- MOV AL,01000010b ; Block verify
- OUT 0Bh,AL ; ...on channel 2 of DMA chip
- MOV AL,01000011b ; Block verify
- OUT 0Bh,AL ; ...on channel 3 of DMA chip
- MOV AL,0FFh ; Refresh byte count
- OUT 1,AL ; ...send lo order
- OUT 1,AL ; ...send hi order
- MOV AL,0 ; Initialize 8237 command reg
- OUT 8,AL ; ...with zero
- OUT 0Ah,AL ; Enable DMA on all channels
- MOV AL,00110110b ; Set up 8253 timer chip
- OUT 43h,AL ; ...chan 0 is time of day
- MOV AL,0 ; Request a divide by
- OUT 40h,AL ; ...65536 decimal
- OUT 40h,AL ; ...0000h or 18.2 tick/sec
- MOV DX,213h ; Expansion unit port
- MOV AL,1 ; ...enable it
- OUT DX,AL ; ...do the enable
- MOV AX,40h ; Get bios impure segment
- MOV DS,AX ; ...into DS register
- MOV SI,DS:72h ; Save reset flag in SI reg
- XOR AX,AX ; ...cause memory check
- MOV BP,AX ; ...will clobber the flag
- MOV BX,AX ; Start at segment 0000h
- MOV DX,55AAh ; ...get pattern
- CLD ; Strings auto-increment
-
- MEMSIZ: XOR DI,DI ; Location XXXX:0
- MOV ES,BX ; ...load segment
- MOV ES:[DI],DX ; ...write pattern
- CMP DX,ES:[DI] ; ...compare
- JNZ MEM_ND ; ...failed, memory end
- MOV CX,2000h ; Else zero 16 kilobytes
- REPZ STOSW ; ...with instruction
- ADD BH,4 ; ...get next 16K bytes
- ifdef MAX_MEMORY
- CMP BH,MAX_MEMORY SHR 2 ; Found max legal user ram?
- else
- CMP BH,0A0h ; Found max legal IBM ram?
- endif
- JNZ MEMSIZ ; ...no, then check more
-
- MEM_ND: MOV DS:72h,SI ; Save pointer
- XOR AX,AX
- MOV ES,AX ; ES = vector segment
- MOV AX,80h
- MOV SS,AX ; Set up temporary stack at
- MOV SP,100h ; 0080:0100 for memory check
- PUSH BP
- PUSH BX
- MOV BP,2
- CALL MEMTST ; Memory check ES:0 - ES:0400
- POP AX
- MOV CL,6
- SHR AX,CL
- MOV DS:13h,AX
- POP AX
- JNB MEM_01
- OR AL,ER_MEM ; Show vector area bad
-
- MEM_01: MOV DS:15h,AL ; Save IPL error code
- XOR AX,AX
- PUSH AX
- PUSH AX
- PUSH AX
- PUSH AX
- PUSH AX
- MOV AX,30h ; Set up IBM-compatible stack
- MOV SS,AX ; ...segment 0030h
- MOV SP,100h ; ...offset 0100h
- PUSH DS
- MOV BX,0E000h ; Check BIOS eprom
- PUSH CS
- POP DS ; ...at F000:E000
- MOV AH,1
- CALL CHKSUM ; ...for valid checksum
- POP DS ; ...restore impure<-DS
- JZ IC8259
- OR Byte ptr DS:15h,ER_BIOS ; Checksum error BIOS eprom
-
- IC8259: CLI ; Init interrupt controller
- MOV AL,13h
- OUT 20h,AL
- MOV AL,8
- OUT 21h,AL
- MOV AL,9
- OUT 21h,AL
- MOV AL,0FFh
- OUT 21h,AL
- PUSH DS
- XOR AX,AX ; 8 nonsense vectors begin table
- MOV ES,AX ; ...at segment 0000h
- PUSH CS
- POP DS
- MOV CX,8 ; Vectors 00h - 07h unused
- XOR DI,DI ; ...we start at vec 00h
-
- LO_VEC: MOV AX,offset IGNORE ; Nonsense interrupt from RSX
- STOSW
- MOV AX,CS ; ...bios ROM segment
- STOSW
- LOOP LO_VEC
-
- MOV SI,offset VECTORS ; SI --> Vector address table
- MOV CX,18h ; ... vectors 08h - 1Fh busy
-
- HI_VEC: MOVSW ; Get INTERRUPT bios ROM offset
- MOV AX,CS
- STOSW ; ...INTERRUPT bios ROM segment
- LOOP HI_VEC
-
- MOV AX,0F600h ; AX --> Rom basic segment
- MOV DS,AX ; DS --> " " "
- XOR BX,BX ; BX = Rom basic offset
- MOV AH,4 ; Four basic roms to check
-
- MOV BP,SP ; Save the stack pointer
- PUSH CS ; ...push code segment
- MOV DX,offset SKIP ; Save the code offset
- PUSH DX ; ...for RAM_PATCH subroutine
- MOV DX,0EA90h ; Mov DX,'NOP,JMP_FAR'
- PUSH DX ; ...save it on stack
- MOV DX,0178Bh ; Mov DX,'MOV DX,[BX]'
- PUSH DX ; ...save it on stack
- PUSH SS ; Save stack segment
- MOV DX,SP ; ...get the stack offset
- ADD DX,02h ; ...calculate xfer addr.
- PUSH DX ; ...save it on the stack
- ;
- RETF ; Test for BASIC rom
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; MOV DX,[BX] ; Executes off the stack ;
- ; JMPF 0F000h,SKIP ; ...in RAM space ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- SKIP: MOV SP,BP ; Restore the stack pointer
- CMP DL,DH ; ...compare 1st and 2nd byte
- JE kosher ; ...perfection. No piracy
-
- B_ROM: CALL CHKSUM ; Scan for BASIC roms
- JNZ kosher ; ...bad basic rom
- DEC AH ; Continue
- JNZ B_ROM ; ...yes, more
-
- POP DS ; Else valid basic
- MOV DI,60h ; ...install basic
-
- XOR AX,AX ; ...zero BASIC interrupt
- STOSW ; ...offset
- MOV AX,0F600h ; ...F600h BASIC interrupt
- STOSW ; ...segment
-
- PUSH DS
- kosher: POP DS ; Setup special low vectors
- MOV Word ptr ES:8,offset int_2 ; ...NMI interrupt
- MOV Word ptr ES:14h,offset int_5 ; ...print screen interrupt
- MOV Word ptr ES:7Ch,0 ; No special graphics chars.
- MOV Word ptr ES:7Eh,0 ; ...so zero vector 1Fh
- MOV DX,61h
- IN AL,DX ; Read machine flags
- OR AL,00110000b ; ...clear old parity error
- OUT DX,AL ; Write them back to reset
- AND AL,11001111b ; ...enable parity
- OUT DX,AL ; Write back, parity enabled
- MOV AL,80h ; ...allow NMI interrupts
- OUT 0A0h,AL
- MOV AX,0000000000110000b ; Assume monochrome video
- MOV DS:10h,AX ; ...card has been installed
- INT 10h ; ...initialize if present
- MOV AX,0000000000100000b ; Assume color/graphics video
- MOV DS:10h,AX ; ...card has been installed
- INT 10h ; ...initialize if present
- IN AL,62h ; Get memory size (64K bytes)
- AND AL,00001111b ; ...in bits 2,3 lo nibble
- MOV AH,AL ; Save memory size nibble
- MOV AL,10101101b
- OUT 61h,AL
- IN AL,62h ; Get no. of floppies (0-3)
- MOV CL,4 ; ...and init. video mode
- SHL AL,CL ; ...shift in hi nibble
- OR AL,AH
- MOV AH,0
- MOV DS:10h,AX ; Start building Equipment Flag
- AND AL,00110000b ; ...if video card, mode set
- JNZ LE232 ; ...found video interface
- MOV AX,offset DUMMY ; No hardware, DUMMY: becomes
- MOV ES:40h,AX ; ...INT_10 video service
- JMP short LE235
-
- LE232: CALL V_INIT ; Setup video
-
- LE235: MOV AL,00001000b ; Read low switches
- OUT 61h,AL
- MOV CX,2956h
-
- WAIT_1: LOOP WAIT_1
- MOV AL,11001000b ; Keyboard acknowledge
- OUT 61h,AL ; ...send the request
- XOR AL,10000000b ; Toggle to enable
- OUT 61h,AL ; ...send key enable
- MOV AX,1Eh ; Offset to buffer start
- MOV DS:1Ah,AX ; Buffer head pointer
- MOV DS:1Ch,AX ; Buffer tail pointer
- MOV DS:80h,AX ; Buffer start
- ADD AX,20h ; ...size
- MOV DS:82h,AX ; Buffer end
- JMP short V_CONT
-
- FAO: MOV DL,AL ; Formatted ascii output
-
- FAO_1: MOV AX,BX ; Get position for
- CALL LOCATE ; ...cursor routine
- PUSH SI ; Get string address
- CALL PRINT ; ...print string
- MOV AX,ES:[BP+0] ; Get port # to print
- CALL BIGNUM ; ...four digits
- POP SI ; Restore string address
- INC BP ; ...Address of port
- INC BP ; ...is two bytes long
- INC BH ; ...down one line
- DEC DL ; Decrement device count
- JNZ FAO_1 ; ...back for more
- RET
-
- K_BYTE: CLC ; Say no error
- MOV AL,DL ; ...size "checked"
- INC AL ; ...show more
- DAA
- MOV DL,AL
- JNB KBY_01
- MOV AL,DH ; ...do carry
- ADC AL,0
- DAA
- MOV DH,AL
-
- KBY_01: MOV AL,DH
- CALL DIGIT ; Print hex digit
- MOV AL,DL
- MOV CL,4
- ROR AL,CL
- CALL DIGIT ; Print hex digit
- MOV AL,DL
- CALL DIGIT ; Print hex digit
- RET
-
- TIMER: MOV DX,241h ; Check for timer #2 port
- CLI
- IN AL,DX ; ..read BCD seconds/100
- STI
- CMP AL,99h ; Are BCD digits in range?
- JBE SER_01 ; ...yes, port exists
- ;
- MOV DX,341h ; Check for timer #1 port
- CLI
- IN AL,DX ; ..read BCD seconds/100
- STI
- CMP AL,99h ; Are BCD digits in range?
- JBE SER_01 ; ...yes, port exists
- ;
- STC ; No hardware, ports 0FFh
- RET
-
- SER_01: CLC ; Found timer(s) answering
- RET
-
- V_CONT: MOV BP,4 ; Assume monochrome, 4K memory
- MOV BX,0B000h ; ...segment in BX
- MOV AL,DS:49h ; Get the video mode
- CMP AL,7 ; ...was it mono?
- JZ M_SEG ; ...yes, skip
- MOV BP,10h ; Else CGA, has 16K memory
- MOV BX,0B800h ; ...segment in BX
-
- M_SEG: PUSH BX ; Load video seg in ES
- POP ES
- MOV AL,DS:65h ; Get CRT hardware mode
- AND AL,11110111b ; ...disable video
- MOV DX,DS:63h ; Get 6845 index port
- ADD DX,4 ; ...add offset for
- OUT DX,AL ; 6845 controller port
-
- CRTRAM: CALL MEMTST ; Memory check ES:0 - ES:0400
- DEC BP
- JNZ CRTRAM ; Loop until CRT RAM checked
- JNB LE2F5
- OR Byte ptr DS:15h,ER_CRT ; Set CRT RAM error in status
-
- LE2F5: CALL V_INIT
- MOV AX,1414h ; Time-out value seconds
- MOV DS:78h,AX ; ...LPT1
- MOV DS:7Ah,AX ; ...LPT2
- MOV AX,101h ; Time-out value seconds
- MOV DS:7Ch,AX ; ...COM1
- MOV DS:7Eh,AX ; ...COM2
- MOV SI,offset LPTRS ; SI --> LPTR port table
- XOR DI,DI ; ...offset into data seg
- MOV CX,3 ; ...number of printers
-
- NXTPRT: MOV DX,CS:[SI] ; Get LPTR port
- MOV AL,10101010b ; ...write value
- OUT DX,AL ; ...to the LPTR
- MOV AL,11111111b ; Dummy data value
- OUT 0C0h,AL ; ...on the bus
- IN AL,DX ; Read code back
- CMP AL,10101010b ; ...check code
- JNZ NO_LPT ; ...no printer found
- MOV [DI+8],DX ; Save printer port
- INC DI
- INC DI
-
- NO_LPT: INC SI
- INC SI
- LOOP NXTPRT
- MOV AX,DI ; Number of printers * 2
- MOV CL,3 ; ...get shift count
- ROR AL,CL ; ...divide by eight
- MOV DS:11h,AL ; ...save in equip. flag
-
- XOR DI,DI ; com port(s) at 40:00 (hex)
-
- COM_1: MOV DX,3FBh ; COM #1 line control reg.
- MOV AL,00011010b ; ...7 bits, even parity
- OUT DX,AL ; Reset COM #1 line cont. reg
- MOV AL,11111111b ; ...noise pattern
- OUT 0C0h,AL ; Write pattern on data buss
- IN AL,DX ; ...read result from COM #1
- CMP AL,00011010b ; Check if serial port exists
- JNZ COM_2 ; ...skip if no COM #1 port
- MOV Word ptr [DI],3F8h ; Else save port # in impure
- INC DI ; ...potential COM #2 port
- INC DI ; ...is at 40:02 (hex)
-
- COM_2: MOV DX,2FBh ; COM #2 line control reg
- MOV AL,00011010b ; ...7 bits, even parity
- OUT DX,AL ; Reset COM #2 line cont. reg
- MOV AL,11111111b ; ...noise pattern
- OUT 0C0h,AL ; Write pattern on data buss
- IN AL,DX ; ...read results from COM #2
- CMP AL,00011010b ; Check if serial port exists
- JNZ COM_CT ; ...skip if no COM #2 port
- MOV word ptr [DI],2F8h ; Else save port # in impure
- INC DI ; ...total number of serial
- INC DI ; ...interfaces times two
-
- COM_CT: MOV AX,DI ; Get serial interface count
- OR DS:11h,AL ; ...equip. flag
- MOV DX,201h
- IN AL,DX ; Read game controller
- TEST AL,0Fh ; ...anything there?
- JNZ NOGAME ; ...yes, invalid
- OR Byte ptr DS:11h,00010000b ; Else game port present
-
- NOGAME: MOV DX,0C000h ; ROM segment start
- PUSH DS
-
- FNDROM: MOV DS,DX ; Load ROM segment
- XOR BX,BX ; ...ID offset
- MOV AX,[BX] ; Read the ROM id
- CMP AX,0AA55h
- JNZ NXTROM ; ...not valid ROM
- MOV AX,40h
- MOV ES,AX
- MOV AH,0
- MOV AL,[BX+2] ; Get ROM size (bytes * 512)
- MOV CL,5
- SHL AX,CL ; Now ROM size in segments
- ADD DX,AX ; ...add base segment
- MOV CL,4
- SHL AX,CL ; ROM address in bytes
- MOV CX,AX ; ...checksum requires CX
- CALL CHK_01 ; Find ROM checksum
- JNZ BADROM ; ...bad ROM
- PUSH DX
- MOV Word ptr ES:67h,3 ; Offset for ROM being setup
- MOV ES:69h,DS ; Segment for ROM being setup
- CALL Dword ptr ES:67h ; ...call ROM initialization
- POP DX
- JMP short FND_01
-
- BADROM: OR Byte ptr ES:15h,ER_ROM ; ROM present, bad checksum
-
- NXTROM: ADD DX,80h ; Segment for next ROM
-
- FND_01: CMP DX,0F600h ; End of ROM space
- JL FNDROM ; ...no, continue
- POP DS
- IN AL,21h ; Read ic 8259 interrupt mask
- AND AL,10111100b ; ...enable IRQ (0,1,6) ints
- OUT 21h,AL ; (tod_clock,key,floppy_disk)
-
- MOV AH,1
- MOV CH,0F0h
- INT 10h ; Set cursor type
- CALL BLANK ; ...clear display
- PUSH DS
- PUSH CS
- POP DS
- POP ES
- TEST Byte ptr ES:10h,1 ; Floppy disk present?
- JZ FND_02 ; ...no
- CMP Word ptr ES:72h,1234h ; Bios setup before?
- JNZ CONFIG ; ...no
- FND_02: JMP RESET ; Else skip memory check
-
- CONFIG: MOV AX,41Ah ; Where to move cursor
- MOV SI,offset STUF ; ...equipment message
- CALL LOCATE ; ...position cursor
- CALL PRINT ; ...and print string
- MOV AX,51Bh ; New cursor position
- MOV SI,offset STUF_1 ; ...CR/LF
- CALL Locate ; ...position cursor
- CALL PRINT ; ...and print string
- TEST Byte ptr ES:15h,11111111b ; Any error so far?
- JZ VALID ; ...no, skip
- CALL PRINT ; Print string
- MOV AL,ES:15h ; ...get error number
- CALL NUMBER ; ...print hex value
- CALL PRINT ; ...print prompt
- MOV BL,4 ; ...long beep
- CALL BEEP
- CALL GETCH ; Wait for keypress
- PUSH AX ; ...save answer
- CALL OUTCHR ; ...echo answer
- POP AX ; ...get answer
- CMP AL,'Y' ; Was it "Y"
- JZ FND_02 ; ...ok, continue
- CMP AL,'y' ; Was it "y"
- JZ FND_02 ; ...ok, continue
- JMPF 0F000h,COLD ; Else cold reset
-
- VALID: MOV SI,offset STUF_2 ; No errors found, load banner
- CALL PRINT ; ...and print string
- MOV AX,81Eh ; Where to move cursor
- CALL LOCATE ; ...position cursor
- CALL PRINT ; ...and print string
- MOV AX,91Ch ; Where to move cursor
- CALL LOCATE ; ...position cursor
- MOV BL,17h ; Character count
-
- FENCE: MOV AL,'-' ; Load ascii minus
- CALL OUTCHR ; ...and print it
- DEC BL
- JNZ FENCE
- MOV AX,0A21h ; Where to move cursor
- CALL LOCATE ; ...position cursor
- MOV AL,ES:49h ; Get CRT mode
- CMP AL,7
- JZ FEN_01 ; ...monochrome
- MOV SI,offset STUF_3 ; ...color/graphics
-
- FEN_01: CALL PRINT ; Print the string
- MOV BX,0B21h
- MOV AL,ES:11h ; Get equipment byte
- PUSH AX
- MOV CL,6
- ROR AL,CL
- AND AL,3 ; Number of printers
- JZ FEN_02
- MOV BP,8
- MOV SI,offset STUF_4
- CALL FAO ; Formatted ascii output
-
- FEN_02: POP AX ; Equipment byte restore
- MOV SI,offset STUF_5 ; ...game controller
- PUSH AX ; Save a copy of equip. byte
- TEST AL,00010000b
- JZ NO_TOY ; Jump if no game controller
- MOV AX,BX
- CALL LOCATE ; Position cursor
- CALL PRINT ; ...and print string
- INC BH ; ...scroll line
-
- NO_TOY: CALL TIMER ; Timer devices?
- JB NO_TIM ; ...skip if none
- MOV AX,BX
- CALL LOCATE ; Position cursor
- INC BH
- MOV SI,offset STUF_8
- CALL PRINT
-
- NO_TIM: POP AX
- MOV SI,offset STUF_6
- ROR AL,1 ; Check for COM port
- AND AL,3
- JZ NO_COM ; ...skip if no com
- XOR BP,BP
- CALL FAO ; Formatted ascii output
-
- NO_COM: MOV AX,121Ch ; Where to position cursor
- CALL LOCATE ; ...position cursor
- MOV SI,offset STUF_7 ; Memory size string
- CALL PRINT ; ...print string
- PUSH ES
- MOV BP,ES:13h ; Memory size (1 K blocks)
- DEC BP
- DEC BP
- MOV SI,2
- MOV DX,SI
- MOV AX,80h
- MOV ES,AX
-
- CUTE: MOV AX,122Bh ; Cursory check of memory
- CALL LOCATE ; ...position cursor
- CALL K_BYTE ; ...print size in K
- CALL MEMTST ; Memory check ES:0 - ES:0400
- JB BADRAM ; ...bad RAM found (How ???)
- DEC BP
- JNZ CUTE
- POP ES
-
- RESET: MOV BL,2 ; Do a warm boot
- CALL BEEP ; ...short beep
- CALL BLANK ; ...clear display
- MOV Word ptr ES:72h,1234h ; Show cold start done
- MOV AH,1
- MOV CX,607h ; Set underline cursor
- INT 10h
- MOV SI,offset BANNER ; Load banner address
- CALL PRINT ; ...and print string
- INT 19h ; Boot the machine
-
- BADRAM: POP ES
- OR Byte ptr ES:15h,ER_RAM ; Show "Bad Ram" error
- JMP CONFIG
-
- STUF db ' Generic Turbo XT Bios 1987',0
- STUF_1 db CR,LF,0,'System error #',0,', Continue?',0
- STUF_2 db ' ',0,'Interface card list',0,'Monochrome',0
- STUF_3 db 'Color/Graphics',0
- STUF_4 db 'Printer #',0
- STUF_5 db 'Game controller',0
- STUF_6 db 'Async. commu. #',0
- STUF_7 db 'RAM Testing .. 000 KB',0
- STUF_8 db 'Timer',0
-
- ENTRY 0E600h ; Not necessary to IPL here..
-
- IPL: STI ; Called to reboot computer
- XOR AX,AX
- MOV DS,AX
- MOV Word ptr DS:78h,offset INT_1E ; Get disk parameter table
- MOV DS:7Ah,CS ; ...save segment
- MOV AX,4 ; Try up to four times
-
- RETRY: PUSH AX ; Save retry count
- MOV AH,0 ; ...reset
- INT 13h ; ...floppy
- JB FAILED
- MOV AL,1 ; One sector
- MOV AH,2 ; ...read
- XOR DX,DX ; ...from drive 0, head 0
- MOV ES,DX ; ...segment 0
- MOV BX,7C00h ; ...offset 7C00
- MOV CL,1 ; ...sector 1
- MOV CH,0 ; ...track 0
- INT 13h ; ...floppy
- JB FAILED
- JMPF 0000h,7C00h ; Call the boot block
- ;
- FAILED: POP AX ; Get retries
- DEC AL ; ...one less
- JNZ RETRY
-
- NODISK: OR AH,AH ; Disk present?
- JNZ DERROR ; ...yes
- CALL BLANK ; Clear display
- PUSH CS
- POP DS
- MOV SI,offset DSKMSG ; Load disk message
- CALL PRINT ; ...and print string
- CALL GETCH ; ...wait for keypress
- CALL BLANK ; ...clear display
- MOV AX,0FF04h ; Reset retry count
- JMP RETRY ; ...and retry
-
- DERROR: XOR AX,AX ; Error from NEC 765
- MOV DS,AX
- LES AX,Dword ptr DS:60h ; ROM basic vector ES:AX
- MOV BX,ES ; ...get ROM basic segment
- CMP AX,0
- MOV AX,0
- JNZ NODISK ; No ROM basic found
- CMP BX,0F600h
- JNZ NODISK ; Invalid ROM basic segment
- INT 18h ; ...else call ROM basic
-
- DSKMSG db 'Insert diskette in DRIVE A.',CR,LF
- db ' Press any key.',0
-
- ENTRY 0E6F2h ; IBM entry point for INT 19h
-
- INT_19: JMP IPL ; Warm boot
-
- ENTRY 0E729h ; IBM entry point for INT 14h
-
- BAUD dw 0417h ; 110 baud clock divisor
- dw 0300h ; 150 baud clock divisor
- dw 0180h ; 300 baud clock divisor
- dw 00C0h ; 600 baud clock divisor
- dw 0060h ; 1200 baud clock divisor
- dw 0030h ; 2400 baud clock divisor
- dw 0018h ; 4800 baud clock divisor
- dw 000Ch ; 9600 baud clock divisor
-
- INT_14: STI ; Serial com. RS232 services
- PUSH DS ; ...thru IC 8250 uart (ugh)
- PUSH DX ; ...DX = COM device (0 - 3)
- PUSH SI
- PUSH DI
- PUSH CX
- PUSH BX
- MOV BX,40h
- MOV DS,BX
- MOV DI,DX ;
- MOV BX,DX ; RS232 serial COM index (0-3)
- SHL BX,1 ; ...index by bytes
- MOV DX,[BX] ; Convert index to port number
- OR DX,DX ; ...by indexing 40:0
- JZ COM_ND ; ...no such COM device, exit
- OR AH,AH ; Init on AH=0
- JZ COMINI
- DEC AH
- JZ COMSND ; Send on AH=1
- DEC AH
- JZ COMGET ; Rcvd on AH=2
- DEC AH
- JZ COMSTS ; Stat on AH=3
-
- COM_ND: POP BX ; End of COM service
- POP CX
- POP DI
- POP SI
- POP DX
- POP DS
- IRET
-
- COMINI: PUSH AX ; Init COM port. AL has data
- ; = (Word Length in Bits - 5)
- ; +(1 iff two stop bits) * 4
- ; +(1 iff parity enable) * 8
- ; +(1 iff parity even ) * 16
- ; +(BAUD: select 0-7 ) * 32
- MOV BL,AL
- ADD DX,3 ; Line Control Register (LCR)
- MOV AL,80h ; ...index RS232_BASE + 3
- OUT DX,AL ; Tell LCR to set (latch) baud
- MOV CL,4
- ROL BL,CL ; Baud rate selects by words
- AND BX,00001110b ; ...mask off extraneous
- MOV AX,Word ptr CS:[BX+BAUD] ; Clock divisor in AX
- SUB DX,3 ; Load in lo order baud rate
- OUT DX,AL ; ...index RS232_BASE + 0
- INC DX ; Load in hi order baud rate
- MOV AL,AH
- OUT DX,AL ; ...index RS232_BASE + 1
- POP AX
- INC DX ; Find Line Control Register
- INC DX ; ...index RS232_BASE + 3
- AND AL,00011111b ; Mask out the baud rate
- OUT DX,AL ; ...set (censored) init stat
- MOV AL,0
- DEC DX ; Interrupt Enable Reg. (IER)
- DEC DX ; ...index RS232_BASE + 1
- OUT DX,AL ; Interrupt is disabled
- DEC DX
- JMP short COMSTS ; Return current status
-
- COMSND: PUSH AX ; Send AL thru COM port
- MOV AL,3
- MOV BH,00110000b ;(Data Set Ready,Clear To Send)
- MOV BL,00100000b ; ..(Data Terminal Ready) wait
- CALL WAITFR ; Wait for transmitter to idle
- JNZ HUNG ; ...time-out error
- SUB DX,5 ; ...(xmit) index RS232_BASE
- POP CX ; Restore char to CL register
- MOV AL,CL ; ...get copy to load in uart
- OUT DX,AL ; ...transmit char to IC 8250
- JMP COM_ND ; ...AH register has status
-
- HUNG: POP CX ; Transmit error, restore char
- MOV AL,CL ; ...in AL for compatibility
- ; ...fall thru to gen. error
- HUNGG: OR AH,80h ; Set error (=sign) bit in AH
- JMP COM_ND ; ...common exit
-
- COMGET: MOV AL,1 ; Get char. from COM port
- MOV BH,00100000b ; Wait on DSR (Data Set Ready)
- MOV BL,00000001b ; Wait on DTR (Data Term.Ready)
- CALL WAITFR ; ...wait for character
- JNZ HUNGG ; ...time-out error
- AND AH,00011110b ; Mask AH for error bits
- SUB DX,5 ; ...(rcvr) index RS232_BASE
- IN AL,DX ; Read the character
- JMP COM_ND ; ...AH register has status
-
- COMSTS: ADD DX,5 ; Calculate line control stat
- IN AL,DX ; ...index RS232_BASE + 5
- MOV AH,AL ; ...save high order status
- INC DX ; Calculate modem stat. reg.
- IN AL,DX ; ...index RS232_BASE + 6
- JMP COM_ND ; ...save low order status
- ;AX=(DEL Clear_To_Send) * 1
- ; (DEL Data_Set_ready)* 2
- ; (Trailing_Ring_Det.)* 4
- ; (DEL Carrier_Detect)* 8
- ; ( Clear_To_Send )* 16
- ; ( Data_Set_Ready)* 32
- ; ( Ring_Indicator)* 64
- ; ( Carrier_Detect)* 128
- ; **************
- ; ( Char received)* 256
- ; ( Char smothered)* 512
- ; ( Parity error )* 1024
- ; ( Framing error )* 2048
- ; ( Break detected)* 4096
- ; ( Able to xmit )* 8192
- ; ( Transmit idle )*16384
- ; ( Time out error)*32768
-
- POLL: MOV BL,byte ptr [DI+7Ch] ; Wait on BH in status or error
-
- POLL_1: SUB CX,CX ; Outer delay loop
- POLL_2: IN AL,DX ; ... inner loop
- MOV AH,AL
- AND AL,BH ; And status with user BH mask
- CMP AL,BH
- JZ POLLXT ; ... jump if mask set
- LOOP POLL_2 ; Else try again
- DEC BL
- JNZ POLL_1
- OR BH,BH ; Clear mask to show timeout
-
- POLLXT: RET ; Exit AH reg. Z flag status
-
- WAITFR: ADD DX,4 ; Reset the Modem Control Reg.
- OUT DX,AL ; ...index RS232_BASE + 4
- INC DX ; Calculate Modem Status Reg.
- INC DX ; ...index RS232_BASE + 6
- PUSH BX ; Save masks (BH=MSR,BL=LSR)
- CALL POLL ; ...wait on MSR modem status
- POP BX ; ...restore wait masks BH,BL
- JNZ WAITF1 ; ..."Error Somewhere" by DEC
-
- DEC DX ; Calculate Line Status Reg.
- MOV BH,BL ; ...index RS232_BASE + 5
- CALL POLL ; ...wait on LSR line status
-
- WAITF1: RET ; Status in AH reg. and Z flag
-
- ENTRY 0E82Eh ; IBM entry, key bios service
-
- INT_16: STI ; Keyboard bios services
- PUSH DS
- PUSH BX
- MOV BX,40h
- MOV DS,BX ; Load work segment
- OR AH,AH
- JZ KPD_RD ; Read keyboard buffer, AH=0
- DEC AH
- JZ KPD_WT ; Set Z if char ready, AH=1
- DEC AH
- JZ KPD_SH ; Return shift in AL , AH=2
-
- KPD_XT: POP BX ; Exit INT_16 keypad service
- POP DS
- IRET
-
- KPD_RD: CLI ; No interrupts, alters buffer
- MOV BX,DS:1Ah ; ...point to buffer head
- CMP BX,DS:1Ch ; If not equal to buffer tail
- JNZ KPD_R1 ; ...char waiting to be read
- STI ; Else allow interrupts
- JMP KPD_RD ; ...wait for him to type
-
- KPD_R1: MOV AX,[BX] ; Fetch the character
- INC BX ; ...point to next character
- INC BX ; ...char = scan code + shift
- MOV DS:1Ah,BX ; Save position in head
- CMP BX,DS:82h ; ...buffer overflowed?
- JNZ KPD_XT ; ...no, done
- MOV BX,DS:80h ; Else reset to point at start
- MOV DS:1Ah,BX ; ...and correct head position
- JMP KPD_XT
-
- KPD_WT: CLI ; No interrupts, critical code
- MOV BX,DS:1Ah ; ...point to buffer head
- CMP BX,DS:1Ch ; ...equal buffer tail?
- MOV AX,[BX] ; (fetch, look ahead)
- STI ; Enable interrupts
- POP BX
- POP DS
- RETF 2 ; Do IRET, preserve flags
-
- KPD_SH: MOV AL,DS:17h ; Read keypad shift status
- JMP KPD_XT
-
- ENTRY 0E885h ; Align INT_9 at correct place
-
- ASCII db 000h,037h,02Eh,020h ; Scan -> Ascii. Sign bit set
- db 02Fh,030h,031h,021h ; ...if further work needed
- db 032h,033h,034h,035h
- db 022h,036h,038h,03Eh
- db 011h,017h,005h,012h
- db 014h,019h,015h,009h
- db 00Fh,010h,039h,03Ah
- db 03Bh,084h,001h,013h
- db 004h,006h,007h,008h
- db 00Ah,00Bh,00Ch,03Fh
- db 040h,041h,082h,03Ch
- db 01Ah,018h,003h,016h
- db 002h,00Eh,00Dh,042h
- db 043h,044h,081h,03Dh
- db 088h,02Dh,0C0h,023h
- db 024h,025h,026h,027h
- db 028h,029h,02Ah,02Bh
- db 02Ch,0A0h,090h
-
- NOALFA db 032h,036h,02Dh,0BBh ; Non-Alphabetic secondary
- db 0BCh,0BDh,0BEh,0BFh ; ...translation table
- db 0C0h,0C1h,0C2h,0C3h
- db 0C4h,020h,031h,033h
- db 034h,035h,037h,038h
- db 039h,030h,03Dh,01Bh
- db 008h,05Bh,05Dh,00Dh
- db 05Ch,02Ah,009h,03Bh
- db 027h,060h,02Ch,02Eh
- db 02Fh
-
- CTRLUP db 040h,05Eh,05Fh,0D4h ; CTRL uppercase secondary
- db 0D5h,0D6h,0D7h,0D8h ; ...translation table
- db 0D9h,0DAh,0DBh,0DCh ; ...for non-ASCII control
- db 0DDh,020h,021h,023h
- db 024h,025h,026h,02Ah
- db 028h,029h,02Bh,01Bh
- db 008h,07Bh,07Dh,00Dh
- db 07Ch,005h,08Fh,03Ah
- db 022h,07Eh,03Ch,03Eh
- db 03Fh
-
- CTRLLO db 003h,01Eh,01Fh,0DEh ; CTRL lowercase secondary
- db 0DFh,0E0h,0E1h,0E2h ; ...translation table
- db 0E3h,0E4h,0E5h,0E6h ; ...for non-ASCII control
- db 0E7h,020h,005h,005h
- db 005h,005h,005h,005h
- db 005h,005h,005h,01Bh
- db 07Fh,01Bh,01Dh,00Ah
- db 01Ch,0F2h,005h,005h
- db 005h,005h,005h,005h
- db 005h
-
- ALTKEY db 0F9h,0FDh,002h,0E8h ; ALT key secondary
- db 0E9h,0EAh,0EBh,0ECh ; ...translation table
- db 0EDh,0EEh,0EFh,0F0h
- db 0F1h,020h,0F8h,0FAh
- db 0FBh,0FCh,0FEh,0FFh
- db 000h,001h,003h,005h
- db 005h,005h,005h,005h
- db 005h,005h,005h,005h
- db 005h,005h,005h,005h
- db 005h
-
- NUMPAD db '789-456+1230.' ; Keypad secondary tralsator
-
- NUMCTR db 0F7h,005h,004h,005h ; Numeric keypad CTRL sec.
- db 0F3h,005h,0F4h,005h ; ...translation table
- db 0F5h,005h,0F6h,005h
- db 005h
-
- NUMUPP db 0C7h,0C8h,0C9h,02Dh ; Numeric keypad SHIFT sec.
- db 0CBh,005h,0CDh,02Bh ; ...translation table
- db 0CFh,0D0h,0D1h,0D2h
- db 0D3h
-
- INT_9: STI ; Key press hardware interrupt
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
- CLD
- MOV AX,40h
- MOV DS,AX
- IN AL,60h ; Read the scan code data
- PUSH AX ; ...save it
- IN AL,61h ; Get control port status
- PUSH AX ; ...save it
- OR AL,10000000b ; Set "latch" bit to
- OUT 61h,AL ; ...acknowledge data
- POP AX ; Restore control status
- OUT 61h,AL ; ...to enable keyboard
- POP AX ; ...restore scan code
- MOV AH,AL ; Save copy of scan code
- CMP AL,11111111b ; ...check for overrun
- JNZ KY_01 ; ...no, OK
- JMP KY_BEP ; Else beep bell on overrun
-
- KY_EOI: MOV AL,20h ; Send end_of_interrupt code
- OUT 20h,AL ; ...to 8259 interrupt chip
-
- KY_XIT: POP ES ; Exit the interrupt
- POP DS
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP AX
- IRET
-
- KY_01: AND AL,01111111b ; Valid scan code, no break
- CMP AL,46h
- JBE KY_02
- JMP KY_CT8
-
- KY_02: MOV BX,offset ASCII ; Table for ESC thru Scroll Lck
- XLAT CS:[BX] ; ...translate to Ascii
- OR AL,AL ; Sign flags "Shift" type key
- JS KY_FLG ; ...shift,caps,num,scroll etc
- OR AH,AH ; Invalid scan code?
- JS KY_EOI ; ...exit if so
- JMP short KY_ASC ; Else normal character
-
- KY_FLG: AND AL,01111111b ; Remove sign flag bit
- OR AH,AH ; ...check scan code
- JS KY_SUP ; ...negative, key released
- CMP AL,10h ; Is it a "toggle" type key?
- JNB KY_TOG ; ...yes
- OR DS:17h,AL ; Else set bit in "flag" byte
- JMP KY_EOI ; ...and exit
-
- KY_TOG: TEST Byte ptr DS:17h,00000100b ; Control key pressed?
- JNZ KY_ASC ; ...yes, skip
- TEST AL,DS:18h ; Else check "CAPS, NUM, SCRL"
- JNZ KY_EOI ; ...set, invalid, exit
- OR DS:18h,AL ; Show set in "flag_1" byte
- XOR DS:17h,AL ; ...flip bits in "flag" byte
- JMP KY_EOI
-
- KY_SUP: CMP AL,10h ; Released - is it "toggle" key
- JNB KY_TUP ; ...skip if so
- NOT AL ; Else form two's complement
- AND DS:17h,AL ; ...to do BIT_CLEAR "flags"
- CMP AL,11110111b ; ALT key release special case
- JNZ KY_EOI ; ...no, exit
- MOV AL,DS:19h ; Else get ALT-keypad character
- MOV AH,0 ; ...pretend null scan code
- MOV DS:19h,AH ; ...zero ALT-keypad character
- CMP AL,AH ; Was there a valid ALT-keypad?
- JZ KY_EOI ; ...no, ignore, exit
- JMP KY_NUL ; Else stuff it in ASCII buffer
-
- KY_TUP: NOT AL ; Form complement of toggle key
- AND DS:18h,AL ; ...to do BIT_CLEAR "flag_1"
- JMP KY_EOI
-
- KY_ASC: TEST Byte ptr DS:18h,00001000b ; Scroll lock pressed?
- JZ KY_NLK ; ...no
- CMP AH,45h ; Is this a NUM LOCK character?
- JZ KY_03 ; ...no
- AND Byte ptr DS:18h,11110111b ; Else clear bits in "flag_1"
-
- KY_03: JMP KY_EOI ; ...and exit
-
- KY_NLK: TEST Byte ptr DS:17h,00001000b ; ALT key pressed?
- JNZ KY_ALT ; ...yes
- TEST Byte ptr DS:17h,00000100b ; CTRL key pressed?
- JNZ KY_CTL ; ...yes
- TEST Byte ptr DS:17h,00000011b ; Either shift key pressed?
- JNZ KSHIFT ; ...yes
-
- KY_LC: CMP AL,1Ah ; Alphabetic character?
- JA KY_LC1 ; ...no
- ADD AL,'a'-1 ; Else add lower case base
- JMP KY_COM
-
- KY_LC1: MOV BX,offset NOALFA ; Non-alphabetic character
- SUB AL,20h
- XLAT CS:[BX] ; ...do the xlate
- JMP KY_COM
-
- KY_ALT: CMP AL,1Ah ; Control key pressed?
- JA KY_AGN ; ...no, skip
- MOV AL,0 ; Else illegal key press
- JMP KY_BFR
-
- KY_AGN: MOV BX,offset ALTKEY ; Load ALT key translation
- SUB AL,20h ; ...bias to printing char.
- XLAT CS:[BX] ; ...do the translation
- JMP KY_COM
-
- KY_CTL: CMP AH,46h ; Scroll lock key?
- JNZ KY_CT1 ; ...no, skip
- MOV Byte ptr DS:71h,10000000b ; Else CTRL-"Scroll" = break
- MOV AX,DS:80h ; ...get key buffer start
- MOV DS:1Ch,AX ; ...get key tail to start
- MOV DS:1Ah,AX ; ...get key head to start
- INT 1Bh ; Issue a "Break" interrupt
- SUB AX,AX
- JMP KY_CO2
-
- KY_CT1: CMP AH,45h ; Num lock key?
- JNZ KY_CT2 ; ...no, skip
- OR Byte ptr DS:18h,00001000b ; Else show scroll lock
- MOV AL,20h ; ...send end_of_interrupt
- OUT 20h,AL ; ...to 8259 int. controller
- CMP Byte ptr DS:49h,7 ; Monochrome monitor?
- JZ KY_POL ; ...yes, skip
- MOV DX,3D8h ; Else reset mode
- MOV AL,DS:65h ; ...for the
- OUT DX,AL ; ...CGA color card
-
- KY_POL: TEST Byte ptr DS:18h,00001000b ; Wait for him to type
- JNZ KY_POL ; ...not yet
- JMP KY_XIT
-
- KY_CT2: CMP AH,3 ; Is it a Control @ (null) ?
- JNZ KY_CT3 ; ...no
- MOV AL,0 ; Else force a null
-
- KY_CT4: JMP KY_BFR ; ...save in buffer
-
- KY_CT3: CMP AL,1Ah ; Is it a control character?
- JBE KY_CT4 ; ...yes
- MOV BX,offset CTRLLO ; Else non-ascii control
- SUB AL,20h ; ...lower case
- XLAT CS:[BX] ; ...translation
- JMP KY_COM
-
- KSHIFT: CMP AH,37h ; Print_Screen pressed?
- JNZ KY_CT5
- MOV AL,20h ; Yes, send end_of_interrupt
- OUT 20h,AL ; ...to 8259 interrupt chip
- INT 5 ; Request print_screen service
- JMP KY_XIT ; ...and exit key service
-
- KY_CT5: CMP AL,1Ah ; Alphabetic char?
- JA KY_CT6 ; ...no
- ADD AL,'A'-1 ; Yes, add base for alphabet
- JMP KY_COM
-
- KY_CT6: MOV BX,offset CTRLUP ; Non-ascii control
- SUB AL,20h ; ...upper case
- XLAT CS:[BX] ; ...translation
- JMP KY_COM
-
- KY_CT8: SUB AL,47h ; Keypad key, convert origin
- MOV BL,DS:17h ; ...get "flag" byte
- TEST BL,00001000b ; Look for ALT keypad entry
- JNZ KB_NUM ; ...do special entry thing
- TEST BL,00000100b ; CTRL key pressed?
- JNZ KY_CTR ; ...skip if so
- TEST BL,00100000b ; Toggle "Num Lock" ?
- JZ KY_CT9 ; ...no, continue
- TEST BL,00000011b ; Shift keys hit?
- JNZ KY_CTA ; ...no, check "INS"
- JMP KY_CTD ; Else xlat keypad char.
-
- KY_CT9: TEST BL,00000011b ; Shift keys hit?
- JZ KY_CTA ; ...no, check "INS" key
- JMP KY_CTD ; Else xlat keypad char.
-
- KB_NUM: OR AH,AH ; ALT-keypad entry, scan code
- JS KY_EO1 ; ...out of range
- TEST Byte ptr DS:17h,00000100b ; Else check CTRL state
- JZ KY_PAD ; ...not pressed, ALT keypad
-
- KY_PAT: CMP AH,53h ; Patch for CTRL ALT - toggle
- JNZ KY_PA1 ; ...not a DEL (reset)
- MOV Word ptr DS:72h,1234h ; Ctrl-Alt-Del, set init flag
- JMP WARM ; ...do a warm reboot
-
- KY_PA1: CMP AH,4Ah ; Is it a keypad "-" ?
- JNZ KY_PAD ; ...no, skip
- PUSH AX
- PUSH BX
- PUSH CX
- IN AL,61h ; Read equipment flags
- XOR AL,00001100b ; ...toggle speed
- OUT 61h,AL ; Write new flags back
-
- MOV AH,1 ; Video func=Set cursor type
- MOV CX,607h ; ...start at 6, end at 7
- AND AL,4 ; Is turbo mode set?
- JZ KY_CUR ; ...no, keep big cursor
- MOV CH,0 ; Else set tiny cursor
-
- KY_CUR: INT 10h ; Set cursor type service
- MOV BX,DS:80h ; ...get start of key buf
- MOV DS:1Ah,BX ; ...set head to start
- MOV DS:1Ch,BX ; ...set tail to start
- POP CX
- POP BX
- POP AX
-
- KY_PAD: MOV BX,offset NUMPAD ; Get keypad translation table
- XLAT CS:[BX] ; ...convert to number
- CMP AL,'0' ; Is it a valid ASCII digit?
- JB KY_EO1 ; ...no, ignore it
- SUB AL,30h ; Else convert to number
- MOV BL,AL ; ...save a copy
- MOV AL,DS:19h ; Get partial ALT-keypad sum
- MOV AH,0Ah ; ...times 10 (decimal)
- MUL AH
- ADD AL,BL ; Add in new digit to sum
- MOV DS:19h,AL ; ...save as new ALT entry
-
- KY_EO1: JMP KY_EOI ; End_of_interrupt, exit
-
- KY_CTR: OR AH,AH ; Key released?
- JS KY_EO1 ; ...ignore if so
- MOV BX,offset NUMCTR ; Else Numeric Keypad Control
- XLAT CS:[BX] ; ...secondary translate
- JMP short KY_COM ; ...and save it
-
- KY_CTA: CMP AH,0D2h ; Was "INS" key released?
- JNZ KY_CTB
- AND Byte ptr DS:18h,01111111b ; Yes, clear "INS" in "FLAG_1"
- JMP short KY_EO1
-
- KY_CTB: OR AH,AH ; Key released?
- JS KY_EO1 ; ...ignore if so
- CMP AH,52h ; Else check for "INS" press
- JNZ KY_CTC ; ...not "INS" press
- TEST Byte ptr DS:18h,10000000b ; Was INS key in effect?
- JNZ KY_EO1 ; ...yes, ignore
- XOR Byte ptr DS:17h,10000000b ; Else tog "INS" in "FLAG" byte
- OR Byte ptr DS:18h,10000000b ; ...set "INS" in "FLAG_1" byte
-
- KY_CTC: MOV BX,offset NUMUPP ; Numeric Keypad Upper Case
- XLAT CS:[BX] ; ...secondary translation
- JMP short KY_COM
-
- KY_CTD: OR AH,AH ; Was the key released?
- JS KY_EO1 ; ...yes, ignore
- MOV BX,offset NUMPAD ; Load translation table
- XLAT CS:[BX] ; ...do translate
- JMP short KY_COM
-
- KY_COM: CMP AL,5 ; Common entry, char in AL
- JZ KY_EO2 ; ...Control E, ignore
- CMP AL,4
- JA KY_CO1 ; Above Control D
-
- OR AL,10000000b ; Else set sign flag
- JMP short KY_CO2
-
- KY_CO1: TEST AL,10000000b ; Is sign bit set?
- JZ KY_CO3 ; ...skip if so
- AND AL,01111111b ; Else mask sign off
-
- KY_CO2: MOV AH,AL ; Save in high order byte
- MOV AL,0 ; ...set scan code to zero
-
- KY_CO3: TEST Byte ptr DS:17h,01000000b ; Test for "CAPS LOCK" state
- JZ KY_BFR ; ...no, skip
- TEST Byte ptr DS:17h,00000011b ; Test for SHIFT key
- JZ KY_CO4 ; ...skip if no shift
- CMP AL,'A' ; Check for alphabetic key
- JB KY_BFR ; ...not SHIFT_able
- CMP AL,'Z' ; Check for alphabetic key
- JA KY_BFR ; ...not SHIFT_able
- ADD AL,20h ; Else do the shift
- JMP short KY_BFR
-
- KY_CO4: CMP AL,'a' ; Check for alphabetic key
- JB KY_BFR ; ...not SHIFT_able
- CMP AL,'z' ; Check for Alphabetic key
- JA KY_BFR ; ...not SHIFT_able
- SUB AL,20h ; Else do the shift
-
- KY_BFR: MOV BX,DS:1Ch ; BX = tail of buffer
- MOV DI,BX ; ...save it
- INC BX ; ...advance
- INC BX ; ...by word
- CMP BX,DS:82h ; End of buffer reached?
- JNZ KY_CHK ; ...no, skip
- MOV BX,DS:80h ; Else BX = beginning of buffer
-
- KY_CHK: CMP BX,DS:1Ah ; BX = Buffer Head ?
- JNZ KY_STF ; ...no, OK
- JMP short KY_BEP ; Else buffer overrun, beep
-
- KY_STF: MOV [DI],AX ; Stuff scan code, char in bfr
- MOV DS:1Ch,BX ; ...and update bfr tail
-
- KY_EO2: JMP KY_EOI
-
- KY_BEP: MOV AL,20h ; Keyboard beeper routine
- OUT 20h,AL ; ...send end_of_interrupt
- MOV BX,80h ; Cycles in beep
- IN AL,61h ; ...get status
- PUSH AX ; ...save copy
-
- KY_BE1: AND AL,11111100b ; Mask off speaker bits
- OUT 61h,AL ; ...disable speaker
- KY_BE2: MOV CX,64h ; Constant for pitch
- KY_BE3: LOOP KY_BE3 ; ...delay, speaker off
- XOR AL,00000010b
- OUT 61h,AL ; Toggle speaker position
- TEST AL,00000010b ; Full cycle done yet?
- JZ KY_BE2 ; ...no, do other half cycle
- DEC BX ; Else show cycle sent
- JNZ KY_BE1 ; ...more cycles to send
- POP AX
- OUT 61h,AL ; Restore flags
- MOV CX,32h ; Silence counter
- KY_BE4: LOOP KY_BE4 ; Send nothing for while
- JMP KY_XIT
-
- KY_NUL: MOV AH,38h ; ALT key pressed, released
- JMP KY_BFR ; ...for no logical reason
-
- ENTRY 0EC59h ; IBM entry point for floppy
-
- INT_13: STI ; Floppy disk services
- PUSH BP
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
- PUSH BX
- MOV DI,AX ; Request type in DI, for index
- XOR AX,AX
- MOV DS,AX
- LES SI,Dword ptr DS:78h ; Get disk parameter table
- MOV AX,40h
- MOV DS,AX
- MOV BX,5
- MOV AX,ES:[BX+SI] ; Get (Gap Length, DTL) in AX
- PUSH AX ; ...save it
- DEC BX
- DEC BX
- MOV AX,ES:[BX+SI] ; Get (Bytes/sector,EOT) in AX
- PUSH AX ; ...save it
- XCHG CL,DH
- XCHG DL,CL
- PUSH DX ; Push (Head,Drive) swapped
- PUSH CX
- PUSH DI
- MOV BP,SP ; Mark bottom of stack frame
- ifdef SLOW_FLOPPY
- CALL FD_SPD ; ...execute request lo speed
- else
- CALL FD_XQT ; ...execute at current speed
- endif
- MOV AH,ES:[SI+2] ; Get new motor count
- MOV DS:40h,AH ; ...and save it
- MOV AH,DS:41h ; Get completion status
- CMP AH,1 ; ...check for write protect
- CMC ; ...was write protect error
- POP BX
- POP CX
- POP DX
- XCHG DL,CL
- XCHG CL,DH
- POP BX ; Clean
- POP BX ; ...up
- POP BX ; ...stack
- POP ES
- POP DS
- POP DI
- POP SI
- POP BP
- RETF 2
-
- FD_XQT: MOV AL,[BP+1] ; Get floppy service number
- OR AL,AL
- JZ FD_RST ; ...reset, AH=0
- DEC AL
- JZ FD_XQ3 ; ...read status, AH=1
- CMP Byte ptr [BP+2],3 ; For track number above 3?
- JA FD_XQ1 ; ...yes
- CMP AL,5 ; Service within range?
- JBE FD_XQ2 ; ...yes
-
- FD_XQ1: MOV Byte ptr DS:41h,1 ; Say write protect error
- RET
-
- FD_XQ2: JMP FD_001 ; Execute legal service
-
- FD_XQ3: MOV AL,DS:41h ; Return NEC status byte
- RET
-
- FD_RST: MOV DX,3F2h ; Reset the floppy disk system
- CLI
- AND Byte ptr DS:3Fh,00001111b ; Clear "write in progress"
- MOV AL,DS:3Fh ; ...find out busy drives
- MOV CL,4
- SHL AL,CL
- TEST AL,00100000b
- JNZ FD_RS1 ; Drive #1 active
- TEST AL,01000000b
- JNZ FD_RS2 ; Drive #2 active
- TEST AL,10000000b
- JZ FD_RS0 ; Drive #3 idle
-
- FD_RS3: INC AL
- FD_RS2: INC AL
- FD_RS1: INC AL
-
- FD_RS0: MOV Byte ptr DS:3Eh,0 ; All drives need recalibrate
- MOV Byte ptr DS:41h,0 ; ...no completion status
- OR AL,00001000b ; Interrupt ON in command word
- OUT DX,AL ; ...send word to controller
- OR AL,00000100b ; "Reset" in command word
- OUT DX,AL ; ...send word to controller
- STI
- CALL NC_BSY ; Wait for completion
- CALL NC_STS ; ...read result block
- MOV AL,DS:42h
- CMP AL,0C0h ; Did the reset work
- JZ FD_RS4 ; ...yes
- MOV Byte ptr DS:41h,20h ; Else set controller error
- JMP short FD_RS5 ; ...return
-
- FD_RS4: MOV AL,3 ; Specify command to NEC
- CALL NEC765 ; ...send it
- MOV AL,ES:[SI] ; First byte in param block
- CALL NEC765 ; ...send it
- MOV AL,ES:[SI+1] ; Secnd byte in param block
- CALL NEC765 ; ...send it
-
- FD_RS5: RET
-
- NECFUN db 003h,000h,0E6h,0C5h,0E6h,04Dh ; NEC function table lookup
- NECDMA db 000h,000h,046h,04Ah,042h,04Ah ; DMA modes for 8237
- NECWRT db 000h,000h,000h,080h,000h,080h ; Write flag table lookup
- NECDRV db 1,2,4,8 ; Drive number table lookup
- NECERR db 80h,20h,10h,4,2,1 ; Error code table lookup
- NECSTS db 04h,10h,08h,04h,03h,02h,20h ; Disk status table lookup
-
- FD_001: CLI ; Normal (non-reset) commands
- MOV Byte ptr DS:41h,0 ; ...reset status
- MOV AL,[BP+1] ; Get command word
- MOV AH,0
- MOV DI,AX ; Save copy, zero-extended
- OUT 0Ch,AL ; ...diddle LSB/MSB flip-flop
- MOV AL,CS:[DI+NECDMA] ; Fetch DMA mode
- OUT 0Bh,AL ; ...send it to IC8237
- MOV AX,[BP+0Ch] ; Get segment address
- MOV CL,4 ; ...convert
- ROL AX,CL ; ...to (offset, 64K page no)
- MOV CH,AL ; Extract page number (0-15.)
- AND CH,00001111b ; ...for 8237 dma controller
- AND AL,11110000b ; Extract implicit page offset
- ADD AX,[BP+0Ah] ; ...add explicit user offset
- ADC CH,0 ; ...(page number overflowed)
- MOV DX,AX ; Now save lo 16 bits of addr.
- OUT 4,AL ; ...send lowest 8 bits " "
- MOV AL,AH
- OUT 4,AL ; ...send next 8 bits " "
- MOV AL,CH
- OUT 81h,AL ; 64K page no to DMA page reg
- MOV AH,[BP+0]
- MOV AL,0
- SHR AX,1 ; Sector cnt * 128
- MOV CL,[BP+6] ; Track count
- SHL AX,CL ; * sector count
- DEC AX ; - 1
- OUT 5,AL ; Send 1/2 of the word count
- XCHG AL,AH
- OUT 5,AL ; Send 2/2 of the word count
- XCHG AL,AH
- ADD AX,DX ; Compute final address
- JNB FD_002 ; ...ok
- STI
- MOV Byte ptr DS:41h,9h ; Else wrapped around 64K byte
- JMP FD_64K ; ...page register
-
- FD_002: MOV AL,2 ; Disable floppy disk dma
- OUT 0Ah,AL
- MOV Byte ptr DS:40h,0FFh ; Set large motor timeout
- MOV BL,[BP+2] ; ...get drive number
- MOV BH,0
- MOV AL,CS:[BX+NECDRV] ; Table lookup bit position
- MOV CH,AL ; ...save mask
- MOV CL,4
- SHL AL,CL ; Shift mask into place
- OR AL,BL ; ...or in drive select
- OR AL,0Ch ; ...or in DMA and NO RESET
- MOV DX,3F2h
- OUT DX,AL ; Send to floppy control port
- STI
- MOV AL,CS:[DI+NECWRT] ; Table lookup for write flag
- OR DS:3Fh,AL ; ...set write flag if active
- OR AL,AL
- JNS FD_003 ; ...skip if non-write
- MOV AH,ES:[SI+0Ah] ; Motor start from param blk
- OR AH,AH
- JZ FD_003 ; ...none specified
- TEST CH,DS:3Fh ; Was this drive motor running?
- JNZ FD_003 ; ...skip if so
- CALL FD_WT1 ; Else delay for motor start
-
- FD_003: OR DS:3Fh,CH ; Show this motor is running
- TEST CH,DS:3Eh ; Drive recalibration needed?
- JNZ FD_004 ; ...no, skip
- OR DS:3Eh,CH ; Else show recalibrated
- MOV AL,7 ; Send RECAL command
- CALL NEC765 ; ...to NEC 765 chip
- MOV AL,BL
- CALL NEC765 ; ...drive number
- CALL NC_BSY ; Wait for completion of RECAL
- CALL NEC_04 ; ...dummy call to RET
-
- FD_004: MOV AL,0Fh ; Request a seek
- CALL NEC765 ; ...from the NEC 765
- MOV AL,BL
- CALL NEC765 ; Drive number
- MOV AL,[BP+3]
- CALL NEC765 ; Cylinder number
- CALL NC_BSY ; ...wait for completion
- CALL NC_STS ; ...read results
- MOV AL,ES:[SI+9] ; Get head settle time
- OR AL,AL ; ...none specified?
- JZ FD_005 ; ...if none, skip
-
- FD_STL: MOV CX,226h ; Delay time for head settle
-
- FD_STZ: LOOP FD_STZ ; ...timed wait
- DEC AL ; ...delay in millisec
- JNZ FD_STL ; ...wait some more
-
- FD_005: MOV AL,CS:[DI+NECFUN] ; Translate user service, then
- CALL NEC765 ; ...and send as NEC func
- MOV AL,[BP+4] ;
- AND AL,1
- SHL AL,1
- SHL AL,1
- OR AL,BL
- CALL NEC765
- CMP Byte ptr [BP+1],5 ; Is this a format request?
- JNZ FD_006 ; ...skip if not
- MOV AL,[BP+6] ; Else use user bytes/sector
- CALL NEC765
- MOV AL,[BP+7] ; ... user EOT
- CALL NEC765
- MOV AL,ES:[SI+7] ; Disk table format gap length
- CALL NEC765
- MOV AL,ES:[SI+8] ; Disk table format fill byte
- CALL NEC765
- JMP short FD_008
-
- FD_006: MOV CX,7 ; Else lookup bytes * 512/sec
- MOV DI,3 ; ...from disk table
-
- FD_007: MOV AL,[BP+DI] ; AL has bytes/sector * 512
- CALL NEC765
- INC DI ; ...get next item for table
- LOOP FD_007 ; ...also (EOT,GAP,DTL...)
-
- FD_008: CALL NC_BSY ; Wait on floppy i/o completion
- CALL NC_ST1 ; ...get NEC status
- MOV AL,DS:42h ; ...into AL
- AND AL,11000000b ; Isolate errors
- JZ FD_012 ; ...no errors
- CMP AL,40h ; Test direction bit
- JZ FD_ERR
- MOV Byte ptr DS:41h,20h ; Set if bad controller
- JMP short FD_012 ; ...return error
-
- FD_ERR: MOV AL,DS:43h ; Read return code from block
- MOV CX,6 ; ...number of error types
- XOR BX,BX ; Start at error type 0
-
- FD_009: TEST AL,CS:[BX+NECERR] ; Has error type BX occured?
- JNZ FD_010 ; ...yes
- INC BX ; Else try next error type
- LOOP FD_009 ; ...until done
-
- FD_010: MOV AL,CS:[BX+NECSTS] ; Translate error code again
- MOV DS:41h,AL ; ...store it as disk status
-
- FD_012: MOV AL,DS:45h ; Get bytes read
- CMP AL,[BP+3] ; ...compare with requested
- MOV AL,DS:47h ; Read sectors requested
- JZ FD_013 ; ...return if all read
- MOV AL,[BP+7] ; Else read sectors requested
- INC AL ; ...add one for luck
-
- FD_013: SUB AL,[BP+5] ; Subtract stectors read
- RET
-
- FD_64K: MOV AL,0 ; Overflowed 64K page boundary
- RET ; ...show no sectors read
-
- NC_BSY: STI ; Wait for operation to finish
- XOR CX,CX ; ...zero lo order delay
- MOV AL,2 ; Load hi order delay
-
- NC_BS1: TEST Byte ptr DS:3Eh,10000000b ; Has interrupt set the flag?
- CLC ; ...hack to slow CPU
- JNZ NC_BS2 ; ...yes
- LOOP NC_BS1 ; Else back for more
- DEC AL
- JNZ NC_BS1
-
- MOV Byte ptr DS:41h,80h ; Time-out, say it completed
- POP AX
- MOV AL,0 ; ...return time out code
- STC ; ...error status
- RET
-
- NC_BS2: AND Byte ptr DS:3Eh,01111111b ; Mask off completion status
- RET ; ...return carry clear
-
- NC_RDY: PUSH CX ; Wait for NEC ready for comand
- XOR CX,CX
- MOV DX,3F4h ; ...NEC status port
-
- NC_RD1: IN AL,DX ; Read status of NEC 765 chip
- OR AL,AL
- JS NC_RD2 ; ...able to accept command
- LOOP NC_RD1
- MOV Byte ptr DS:41h,80h ; Else show timeout error
- JMP short NC_RD3
-
- NC_RD2: TEST AL,01000000b ; Test the direction bit
- JNZ NC_RD4
- MOV Byte ptr DS:41h,20h ; ...clear iff controller err
-
- NC_RD3: POP CX
- STC
- RET
-
- NC_RD4: INC DX ; Load NEC data port
- IN AL,DX ; ...read it
- PUSH AX
-
- MOV CX,0Ah ; Short delay
- NC_RD5: LOOP NC_RD5
-
- DEC DX ; Load NEC status port
- IN AL,DX ; ...read status
- TEST AL,00010000b ; ...set Z flag if done
- CLC ; ...return success
- POP AX
- POP CX
- RET
-
- FD_WT1: PUSH CX ; Millisecond delay in AH
- FD_WT2: XOR CX,CX
- FD_WT3: LOOP FD_WT3
- DEC AH
- JNZ FD_WT2
- POP CX
- RET
-
- ifdef SLOW_FLOPPY ; Run floppy at SLOWEST speed
-
- FD_SPD: IN AL,61h ; Toggle speed on Floppy Disk
- PUSH AX ; ...save old clock rate
- AND AL,11110011b ; ...load slowest clock rate
- OUT 61h,AL ; ...slow down to 4.77 mHz
- CALL FD_XQT ; Execute the i/o request
- POP AX ; ...restore old clock rate
- OUT 61h,AL ; ...from saved clock byte
- RET
- endif
-
- ENTRY 0EF57h ; Disk interrupt entry
-
- INT_E: STI ; Floppy disk attention
- PUSH DS
- PUSH AX
- MOV AX,40h
- MOV DS,AX
- OR Byte ptr DS:3Eh,10000000b ; Raise "attention" flag
- MOV AL,20h ; Send end_of_interrupt code
- OUT 20h,AL ; ...to 8259 interrupt chip
- POP AX
- POP DS
- IRET
-
- NC_STS: MOV AL,8 ; Send a "Request status"
- CALL NEC765 ; ...to the NEC 765 chip
-
- NC_ST1: PUSH BX ; Alternate entry point
- PUSH CX
- MOV CX,7
- XOR BX,BX
-
- NC_ST2: CALL NC_RDY ; Wait for NEC 765 ready
- JB NC_ST3 ; ...NEC 765 error
- MOV [BX+42h],AL ; Save status in BIOS block
- JZ NC_ST4 ; ...NEC 765 ready
- INC BX ; Count more
- LOOP NC_ST2
- MOV Byte ptr DS:41h,20h ; NEC 765 controller error
-
- NC_ST3: STC ; Set error condition
- POP CX
- POP BX
- POP AX
- MOV AL,0
- RET
-
- NC_ST4: POP CX ; Successful return
- POP BX
- RET
-
- NEC765: PUSH CX ; Send control to NEC 765 chip
- PUSH DX
- PUSH AX
- XOR CX,CX
- MOV DX,3F4h ; Load NEC 765 status port
-
- NEC_01: IN AL,DX ; Read NEC 765 status
- OR AL,AL
- JS NEC_02 ; ...done
- LOOP NEC_01
- MOV Byte ptr DS:41h,80h ; Set time out status
- JMP short NEC_05
-
- NEC_02: TEST AL,40h ; Check data direction
- JZ NEC_03
- MOV Byte ptr DS:41h,20h ; ...NEC 765 is gimped
- JMP short NEC_05
-
- NEC_03: INC DX ; Load NEC 765 data port
- POP AX
- OUT DX,AL ; ...write user's parameter
- CLC
- POP DX
- POP CX
- NEC_04: RET
-
- NEC_05: POP AX ; Common error return
- POP DX
- POP CX
- POP AX
- MOV AL,0
- STC
- RET
-
- ENTRY 0EFC7h ; IBM entry for disk param
-
- INT_1E: db 11001111b ; Disk parameter table
- db 2
- db 25h
- db 2
- db 8
- db 2Ah
- db 0FFh
- db 50h
- db 0F6h
- db 19h
- db 4
-
- ENTRY 0EFD2h ; IBM entry for parallel LPT
-
- INT_17: STI ; Parallel printer services
- PUSH DS
- PUSH BX
- PUSH CX
- PUSH DX
- MOV BX,40h
- MOV DS,BX
- MOV BX,DX ; DX is printer index (0 - 3)
- SHL BX,1 ; ...word index
- MOV DX,[BX+8] ; Load printer port
- OR DX,DX
- JZ LP_01 ; Goes to black hole
- OR AH,AH
- JZ LP_02 ; Function is print, AH=0
- DEC AH
- JZ LP_INI ; Function is init , AH=1
- DEC AH
- JZ LP_STS ; Get the status , AH=2
-
- LP_01: POP DX
- POP CX
- POP BX
- POP DS
- IRET
-
- LP_02: OUT DX,AL ; Char --> data lines 0-7
- INC DX ; Printer status port
- MOV BH,[BX+78h] ; Load time out parameter
- MOV AH,AL
-
- LP_05: XOR CX,CX ; Clear lo order time out
-
- LP_POL: IN AL,DX ; Get line printer status
- OR AL,AL ; ...ready?
- JS LP_DON ; ...done if so
- LOOP LP_POL
- DEC BH ; Decrement hi order time out
- JNZ LP_05
-
- OR AL,00000001b ; Set timeout in Status Byte
- AND AL,11111001b ; ...bits returned to caller
- JMP short LP_TOG
-
- LP_DON: INC DX ; Printer control port
- MOV AL,00001101b ; Set output strobe hi
- OUT DX,AL ; ...data lines 0-7 valid
-
- LP_STR: MOV AL,00001100b ; Set output strobe lo
- OUT DX,AL ; ...data lines 0-7 ?????
- DEC DX ; Printer status port
- JMP short LP_ST1 ; ...get line printer status
-
- LP_STS: MOV AH,AL ; Save copy of character
- INC DX ; Printer status port
-
- LP_ST1: IN AL,DX ; Read printer status
- AND AL,11111000b ; ...bits returned to caller
-
- LP_TOG: XOR AL,01001000b ; ...toggle ERROR,ACKNOWLEDGE
- XCHG AL,AH
- JMP LP_01 ; Exit, AH=Status,AL=character
-
- LP_INI: MOV AH,AL ; Initialize the line printer
- INC DX
- INC DX
- MOV AL,00001000b
- OUT DX,AL ; Request initialize
- MOV CX,5DCh ; ...delay
- LP_DLY: LOOP LP_DLY
- JMP LP_STR ; Strobe the line printer
-
- ENTRY 0F045h ; IBM entry point for table
-
- V_TABLE dw CRT_0 ; Set mode
- dw CRT_1 ; Set cursor type
- dw CRT_2 ; Set cursor position
- dw CRT_3 ; Get cursor position
- dw CRT_4 ; Read light pen position
- dw CRT_5 ; Set active display page
- dw CRT_6 ; Scroll active page up
- dw CRT_7 ; Scroll active page down
- dw CRT_8 ; Read attribute/character
- dw CRT_9 ; Write attribute/character
- dw CRT_10 ; Read character only
- dw CRT_11 ; Set color
- dw CRT_12 ; Write pixel
- dw CRT_13 ; Read pixel
- dw CRT_14 ; Write teletype
- dw CRT_15 ; Return current video state
-
- ENTRY 0F065h ; IBM entry, video bios service
-
- INT_10: STI ; Video bios service AH=(0-15.)
- CLD ; ...strings auto-increment
- PUSH BP
- PUSH ES
- PUSH DS
- PUSH SI
- PUSH DI
- PUSH DX
- PUSH CX
- PUSH BX
- PUSH AX
- MOV BX,40h
- MOV DS,BX
- MOV BL,DS:10h ; Get equipment byte
- AND BL,00110000b ; ...isolate video mode
- CMP BL,00110000b ; Check for monochrome card
- MOV BX,0B800h
- JNZ C_01 ; ...not there, BX --> CGA
- MOV BX,0B000h ; Else BX --> MONO
-
- C_01: PUSH BX ; Save video buffer address
- MOV BP,SP ; ...start of stack frame
- CALL C_02 ; ...then do the function
- POP SI
- POP AX
- POP BX
- POP CX
- POP DX
- POP DI
- POP SI
- POP DS
- POP ES
- POP BP
- IRET
-
- MAPBYT: PUSH DX ; Mul AL by BX, CX --> buf
- MOV AH,0
- MUL BX ; Position in AX
- POP DX
- MOV CX,[BP+0] ; CX --> video buffer
- RET
-
- ENTRY 0F0A4h ; IBM entry, SET_MODE tables
-
- INT_1D: db 38h,28h,2Dh,0Ah,1Fh,6,19h ; Init string for 40 x 25
- db 1Ch,2,7,6,7
- db 0,0,0,0
-
- db 71h,50h,5Ah,0Ah,1Fh,6,19h ; Init string for 80 x 25 col
- db 1Ch,2,7,6,7
- db 0,0,0,0
-
- db 38h,28h,2Dh,0Ah,7Fh,6,64h ; Init string for GRAPHIX
- db 70h,2,1,6,7
- db 0,0,0,0
-
- db 61h,50h,52h,0Fh,19h,6,19h ; Init string for 80 x 25 b/w
- db 19h,2,0Dh,0Bh,0Ch
- db 0,0,0,0
-
- REGENL dw 0800h ; Regen len, 40 x 25
- dw 1000h ; 80 x 25
- dw 4000h ; GRAPHIX
- dw 4000h
-
- MAXCOL db 28h,28h,50h,50h,28h,28h,50h,50h ; Maximum columns
-
- MODES db 2Ch,28h,2Dh,29h,2Ah,2Eh,1Eh,29h ; Table of mode sets
-
- TABMUL db 00h,00h,10h,10h,20h,20h,20h,30h ; Table lookup for multiply
-
- C_02: CMP AH,0Fh ; Is AH a legal video command?
- JBE C_03
- RET ; ...error return if not
-
- C_03: SHL AH,1 ; Make word value
- MOV BL,AH ; ...then set up BX
- MOV BH,0
- JMP Word ptr CS:[BX+V_TABLE] ; ...vector to routines
-
- CRT_0: MOV AL,DS:10h ; Set mode of CRT
- MOV DX,3B4h ; ...mono port
- AND AL,00110000b ; ...get display type
- CMP AL,00110000b ; ...equal if mono
- MOV AL,1 ; Assume mono display
- MOV BL,7 ; ...mode is 7
- JZ C0_01 ; ...Skip if mono, else CGA
- MOV BL,[BP+2] ; BL = mode number (user AL)
- MOV DL,0D4h ; 3D4 is CGA port
- DEC AL
-
- C0_01: MOV DS:63h,DX ; Save cur. CRT display port
- ADD DL,4
- OUT DX,AL ; Reset the video
- MOV DS:49h,BL ; ...save cur. CRT mode
- PUSH DS
- XOR AX,AX
- MOV DS,AX
- LES SI,Dword ptr DS:74h ; SI --> INT_1D video param
- POP DS
- MOV BH,0
- PUSH BX
- MOV BL,CS:[BX+TABMUL] ; Get BL for index into INT_1D
- ADD SI,BX
- MOV CX,10h ; Sixteen values to send
-
- C0_02: MOV AL,ES:[SI] ; Value to send in SI
- CALL SENDAX ; ...send it
- INC AH ; ...bump count
- INC SI ; ...point to next
- LOOP C0_02 ; ...loop until done
-
- MOV BX,[BP+0] ; BX --> regen buffer
- MOV ES,BX ; ...into ES segment
- XOR DI,DI
- CALL MODCHK ; Set flags acc. to mode
- MOV CX,2000h ; ...assume CGA
- MOV AX,0 ; ...and graphics
- JB C0_04 ; ...do graphics fill
- JNZ C0_03 ; ...Alphanumeric fill
- MOV CX,800h ; ...mono card
- C0_03: MOV AX,7*100h+' ' ; Word for text fill
- C0_04: REPZ STOSW ; ...fill regen buffer
-
- MOV DX,DS:63h ; Get the port
- ADD DL,4
- POP BX
- MOV AL,CS:[BX+MODES] ; Load data to set for mode
- OUT DX,AL ; ...and send it
- MOV DS:65h,AL ; ...then save active data
- INC DX
- MOV AL,30h ; Assume not 640 x 200 b/w
- CMP BL,6 ; ...correct?
- JNZ C0_05
- MOV AL,3Fh ; Palette for 640 x 200 b/w
-
- C0_05: MOV DS:66h,AL ; ...save palette
- OUT DX,AL ; ...send palette
- XOR AX,AX
- MOV DS:4Eh,AX ; Start at beg. of 1st page
- MOV DS:62h,AL ; ...active page=page 0
- MOV CX,8 ; Do 8 pages of cursor data
- MOV DI,50h ; Page cursor data at 40:50
-
- C0_06: MOV [DI],AX ; Cursor at upper left of page
- INC DI ; ...next page
- LOOP C0_06
- MOV Word ptr DS:60h,0607h ; Cursor: Line 6 thru Line 7
- MOV AL,CS:[BX+MAXCOL] ; Get display width
- MOV DS:4Ah,AX ; ...save it
- AND BL,11111110b
- MOV AX,Word ptr CS:[BX+REGENL] ; Get video regen length
- MOV DS:4Ch,AX ; ...save it
- RET
-
- CRT_1: MOV CX,[BP+6] ; Set cursor type, from CX
- MOV DS:60h,CX ; ...save it
- MOV AH,0Ah ; CRT index register 0Ah
- CALL OT6845 ; ...send CH,CL to CRT reg
- RET
-
- CRT_2: MOV BL,[BP+5] ; Set cursor position, page BH
- SHL BL,1 ; ...(our BL)
- MOV BH,0
- MOV AX,[BP+8] ; Position in user DX (our AX)
- MOV [BX+50h],AX ; ...remember cursor position
- JMP SETCUR ; ...set 6845 cursor hardware
-
- CRT_3: MOV BL,[BP+5] ; Get cursor position, page BH
- SHL BL,1
- MOV BH,0
- MOV AX,[BX+50h]
- MOV [BP+8],AX ; ...return position in user DX
- MOV AX,DS:60h ; Get cursor mode
- MOV [BP+6],AX ; ...return in user CX
- RET
-
- PENOFF: db 3,3,5,5,3,3,3,4 ; Light pen offset table
-
- CRT_4: MOV DX,DS:63h ; Read light pen position
- ADD DL,6
- MOV Byte ptr [BP+3],0 ; AH=0, assume not triggered
- IN AL,DX
- TEST AL,00000100b
- JZ C4_05 ; Skip, reset if pen not set
- TEST AL,00000010b
- JNZ C4_01 ; Skip if pen triggered
- RET ; ...return, do not reset
-
- C4_01: MOV AH,10h ; Offset to pen port is 10h
- CALL PENXY ; ...read into CH,CL
- MOV BL,DS:49h ; Get CRT mode data word
- MOV CL,BL
- MOV BH,0
- MOV BL,Byte ptr CS:[BX+PENOFF] ; Load offset for subtraction
- SUB CX,BX
- JNS C4_02 ; ...did not overflow
- XOR AX,AX ; Else fudge a zero
-
- C4_02: CALL MODCHK ; Set flags on display type
- JNB C4_03 ; ...text mode, skip
- MOV CH,28h
- DIV DL
- MOV BL,AH
- MOV BH,0
- MOV CL,3
- SHL BX,CL
- MOV CH,AL
- SHL CH,1
- MOV DL,AH
- MOV DH,AL
- SHR DH,1
- SHR DH,1
- CMP Byte ptr DS:49h,6 ; Mode 640 x 200 b/w?
- JNZ C4_04 ; ...no, skip
- SHL DL,1
- SHL BX,1
- JMP short C4_04
-
- C4_03: DIV Byte ptr DS:4Ah ; Divide by columns in screen
- XCHG AL,AH ; ...as this is text mode
- MOV DX,AX
- MOV CL,3
- SHL AH,CL
- MOV CH,AH
- MOV BL,AL
- MOV BH,0
- SHL BX,CL
-
- C4_04: MOV Byte ptr [BP+3],1 ; Return AH=1, light pen read
- MOV [BP+8],DX ; ...row, column in user DX
- MOV [BP+4],BX ; ...pixel column in user BX
- MOV [BP+7],CH ; ...raster line in user CH
-
- C4_05: MOV DX,DS:63h ; Get port of active CRT card
- ADD DX,7
- OUT DX,AL ; ...reset the light pen
- RET
-
- CRT_5: MOV AL,[BP+2] ; Set active display page to AL
- MOV DS:62h,AL ; ...save new active page
- MOV AH,0 ; ...clear hi order
- PUSH AX
- MOV BX,DS:4Ch ; Get size of regen. buffer
- MUL BX ; ...times number of pages
- MOV DS:4Eh,AX ; Now AX = CRT offset, save
- SHR AX,1 ; ...now word offset
- MOV CX,AX ; ...save a copy
- MOV AH,0Ch ; CRT index register 0Ch
- CALL OT6845 ; ...send CH,CL thru CRT reg
- POP BX
- CALL MOVCUR ; Save new parameters
- RET
-
- CRT_6: ; Scroll active page up
- CRT_7: CALL MODCHK ; Scroll active page down
- JNB SCR_01
- JMP SCG_01 ; Graphics scroll
-
- SCR_01: CLD ; Strings go upward
- CMP Byte ptr DS:49h,2
- JB SCR_03 ; ...no retrace wait needed
- CMP Byte ptr DS:49h,3
- JA SCR_03 ; ...no retrace wait needed
- MOV DX,3DAh ; Else 80 x 25, do the kludge
-
- SCR_02: IN AL,DX ; Read CGA status register
- TEST AL,00001000b ; ...vertical retrace?
- JZ SCR_02 ; ...wait until it is
- MOV DX,3D8h ; Then go and
- MOV AL,25h ; ...turn the display
- OUT DX,AL ; ...off to avoid snow
-
- SCR_03: MOV AX,[BP+8] ; Get row,column of upper left
- PUSH AX
- CMP Byte ptr [BP+3],7 ; Check for scroll down
- JZ SCR_04 ; ...yes, skip if so
- MOV AX,[BP+6] ; Get row,column of lowr right
-
- SCR_04: CALL RC2COL ; Get byte offset in CRT buf
- ADD AX,DS:4Eh ; ...add base for CRT buf
- MOV SI,AX
- MOV DI,AX
- POP DX
- SUB DX,[BP+6] ; Subtract (row,col) lwr rhgt
- ADD DX,101h ; ...width of one char
- MOV BX,DS:4Ah ; Get columns in display
- SHL BX,1 ; ...bytes in row of display
- PUSH DS
- MOV AL,[BP+2] ; Get scroll fill character
- CALL MAPBYT ; ...calculate offset
- MOV ES,CX ; CX --> byte in buffer
- MOV DS,CX
- CMP Byte ptr [BP+3],6 ; Scroll up?
- JZ SCR_05 ; ...skip if so
- NEG AX
- NEG BX
- STD ; Else start at top of page
-
- SCR_05: MOV CL,[BP+2] ; Get count of lines to scroll
- OR CL,CL
- JZ SCR_07 ; ...nothing to do
- ADD SI,AX
- SUB DH,[BP+2]
-
- SCR_06: MOV CH,0 ; Clear hi order word count
- MOV CL,DL ; ...load lo order word count
- PUSH DI
- PUSH SI
- REPZ MOVSW ; Do the scroll
- POP SI
- POP DI
- ADD SI,BX ; Move one line in direction
- ADD DI,BX ; "" ""
- DEC DH ; One less line to scroll
- JNZ SCR_06
- MOV DH,[BP+2] ; Now get number of rows
-
- SCR_07: MOV CH,0 ; Clear hi order word count
- MOV AH,[BP+5] ; ...get fill attribute
- MOV AL,' ' ; ...fill character
-
- SCR_08: MOV CL,DL ; Get characters to scroll
- PUSH DI
- REPZ STOSW ; ...store fill attr/char
- POP DI
- ADD DI,BX ; Show row was filled
- DEC DH
- JNZ SCR_08 ; ...more rows are left
- POP DS
- CALL MODCHK ; Check for monochrome card
- JZ SCR_09 ; ...skip if so
- MOV AL,DS:65h ; Get the mode data byte
- MOV DX,3D8h ; ...load active CRT card port
- OUT DX,AL ; ...and unblank the screen
-
- SCR_09: RET
-
- SCG_01: CLD ; Assume GRAFIX scroll up
- MOV AX,[BP+8] ; (Row,Col) of lower right
- PUSH AX
- CMP Byte ptr [BP+3],7 ; Scroll down?
- JZ SCG_02 ; ...skip if so
- MOV AX,[BP+6] ; (Row,Col) of upper left
-
- SCG_02: CALL GRAMAP ; Convert (Row,Col) -> Chars
- MOV DI,AX
- POP DX
- SUB DX,[BP+6] ; Chars to copy over
- ADD DX,101h ; ...width of one char
- SHL DH,1
- SHL DH,1
- MOV AL,[BP+3] ; Get command type
- CMP Byte ptr DS:49h,6 ; ...is this 640 x 200?
- JZ SCG_03 ; ...skip if so
- SHL DL,1 ; Else bigger characters
- SHL DI,1
- CMP AL,7 ; Is this scroll down?
- JNZ SCG_03 ; ...skip if not so
- INC DI
-
- SCG_03: CMP AL,7 ; Is this scroll down?
- JNZ SCG_04 ; ...skip if not so
- ADD DI,0F0h
-
- SCG_04: MOV BL,[BP+2] ; Number of rows to blank
- SHL BL,1
- SHL BL,1
- PUSH BX
- SUB DH,BL ; Subtract from row count
- MOV AL,50h
- MUL BL
- MOV BX,1FB0h
- CMP Byte ptr [BP+3],6 ; Is this scroll up?
- JZ SCG_05 ; ...skip if so
- NEG AX ; Else do it
- MOV BX,2050h
- STD ; ...in reverse
-
- SCG_05: MOV SI,DI ; End of area
- ADD SI,AX ; ...start
- POP AX
- OR AL,AL
- MOV CX,[BP+0]
- MOV DS,CX
- MOV ES,CX
- JZ SCG_07 ; No rows to scroll
- PUSH AX
-
- SCG_06: MOV CH,0 ; Zero hi order byte count
- MOV CL,DL ; ...bytes in row
- PUSH SI
- PUSH DI
- REPZ MOVSB ; Copy one plane
- POP DI
- POP SI
- ADD SI,2000h ; Load other grafix
- ADD DI,2000h ; ...video plane
- MOV CL,DL
- PUSH SI
- PUSH DI
- REPZ MOVSB ; Copy other plane
- POP DI
- POP SI
- SUB SI,BX
- SUB DI,BX
- DEC DH ; One less row to scroll
- JNZ SCG_06 ; ...loop if more to do
- POP AX
- MOV DH,AL ; Load rows to blank
-
- SCG_07: MOV AL,[BP+5] ; Get fill attribute
- MOV CH,0
-
- SCG_08: MOV CL,DL ; Get bytes per row
- PUSH DI
- REPZ STOSB ; Load row with fill attr.
- POP DI
- ADD DI,2000h ; Do other grafix video plane
- MOV CL,DL
- PUSH DI
- REPZ STOSB ; Load row with fill attr.
- POP DI
- SUB DI,BX
- DEC DH ; Show one less row to blank
- JNZ SCG_08 ; ...loop if more to do
- RET
-
- CRT_8: ; Read attribute/character
- CRT_9: ; Write attribute/character
- CRT_10: CALL MODCHK ; Write character only
- JB CG8_01 ; ... graphics operation
- MOV BL,[BP+5] ; Get the display page
- MOV BH,0
- PUSH BX
- CALL MPRC2C ; Convert Row,Col,Page -> Col
- MOV DI,AX ; ...offset in DI
- POP AX
- MUL Word ptr DS:4Ch ; Page length X page number
- ADD DI,AX ; ...current char. position
- MOV SI,DI ; ...move into si
- MOV DX,DS:63h ; Display port into DX
- ADD DX,6 ; ...get status port
- PUSH DS
- MOV BX,[BP+0] ; BX --> regen. buffer
- MOV DS,BX
- MOV ES,BX
- MOV AL,[BP+3] ; Get user (AH) func request
- CMP AL,8
- JNZ C9_01 ; ...skip if not read attr
-
- C8_01: IN AL,DX ; Read CRT display status
- TEST AL,00000001b ; ...test for hor. retrace
- JNZ C8_01 ; Yes, wait for display on
- CLI ; ...no interrupts now
-
- C8_02: IN AL,DX ; Read CRT display status
- TEST AL,00000001b ; ...test for hor. retrace
- JZ C8_02 ; ...not yet, wait for it
-
- LODSW ; Read character/attribute
- POP DS
- MOV [BP+2],AL ; Return character
- MOV [BP+3],AH ; ..and attribute
- RET
-
- C9_01: MOV BL,[BP+2] ; Get char. to write
- MOV BH,[BP+4] ; ...attribute
- MOV CX,[BP+6] ; ...character count
- CMP AL,0Ah ; Write char. only?
- JZ CA_01 ; ...skip if so
-
- C9_02: IN AL,DX ; Read CRT display status
- TEST AL,00000001b ; ...test for hor. retrace
- JNZ C9_02 ; Yes, wait for display on
- CLI ; ...no interrupts now
-
- C9_03: IN AL,DX ; Read CRT display status
- TEST AL,00000001b ; ...test for hor. retrace
- JZ C9_03 ; ...not yet, wait for it
-
- MOV AX,BX ; Get char/attribute
- STOSW ; ...write it
- LOOP C9_02 ; ...loop for char. count
- POP DS
- RET
-
- CA_01: IN AL,DX ; Read CRT display status
- TEST AL,00000001b ; ...test for hor. retrace
- JNZ CA_01 ; ...not yet, wait for it
- CLI ; ...no interrupts now
-
- CA_02: IN AL,DX ; Read CRT display status
- TEST AL,00000001b ; ...test for hor. retrace
- JZ CA_02 ; ...not yet, wait for it
-
- MOV AL,BL ; Get character
- STOSB ; ...write it
- INC DI ; ...skip attribute
- LOOP CA_01 ; ...loop for char. count
- POP DS
- RET
-
- CG8_01: CMP Byte ptr [BP+3],8 ; Read graphics char/attr. ?
- JNZ CG9_01 ; ...no, must be write
- JMP CGR_01 ; Else read char/attr.
-
- CG9_01: MOV AX,DS:50h ; Get cursor position
- CALL GRAMAP ; ...convert (row,col) -> col
- MOV DI,AX ; Save in displacement register
- PUSH DS
- MOV AL,[BP+2] ; Get character to write
- MOV AH,0
- OR AL,AL ; Is it user character set?
- JS CG9_02 ; ...skip if so
- MOV DX,CS ; Else use ROM character set
- MOV SI,offset GRAFIX ; ...offset GRAFIX into SI
- JMP short CG9_03
-
- CG9_02: AND AL,7Fh ; Origin to zero
- XOR BX,BX ; ...then go load
- MOV DS,BX ; ...user grafix
- LDS SI,Dword ptr DS:7Ch ; ...vector, offset in SI
- MOV DX,DS ; ...segment into DX
-
- CG9_03: POP DS ; Restore data segment
- MOV CL,3 ; ...char 8 pixels wide
- SHL AX,CL
- ADD SI,AX ; Add regen. buffer base addr.
- MOV AX,[BP+0] ; ...get regen buffer addr.
- MOV ES,AX ; ...into ES
- MOV CX,[BP+6] ; ...load char. count
- CMP Byte ptr DS:49h,6 ; Is the mode 640 x 200 b/w?
- PUSH DS
- MOV DS,DX
- JZ CG8_02 ; ...skip if so
- SHL DI,1
- MOV AL,[BP+4] ; Get char. attribute
- AND AX,3
- MOV BX,5555h
- MUL BX
- MOV DX,AX
- MOV BL,[BP+4]
-
- CG9_04: MOV BH,8 ; Char 8 pixels wide
- PUSH DI
- PUSH SI
-
- CG9_05: LODSB ; Read the screen
- PUSH CX
- PUSH BX
- XOR BX,BX
- MOV CX,8
-
- CG9_06: SHR AL,1 ; Shift bits thru byte
- RCR BX,1
- SAR BX,1
- LOOP CG9_06
-
- MOV AX,BX ; Result into AX
- POP BX
- POP CX
- AND AX,DX
- XCHG AH,AL
- OR BL,BL
- JNS CG9_07
- XOR AX,ES:[DI]
-
- CG9_07: MOV ES:[DI],AX ; Write new word
- XOR DI,2000h
- TEST DI,2000h ; Is this other plane?
- JNZ CG9_08 ; ...nope
- ADD DI,50h ; Else advance character
-
- CG9_08: DEC BH ; Show another char written
- JNZ CG9_05 ; ...more to go
- POP SI
- POP DI
- INC DI
- INC DI
- LOOP CG9_04
- POP DS
- RET
-
- CG8_02: MOV BL,[BP+4] ; Get display page
- MOV DX,2000h ; ...size of grafix plane
-
- CG8_03: MOV BH,8 ; Pixel count to write
- PUSH DI
- PUSH SI
-
- CG8_04: LODSB ; Read from one plane
- OR BL,BL ; ...done both planes?
- JNS CG8_05 ; ...skip if not
- XOR AL,ES:[DI] ; Else load attribute
-
- CG8_05: MOV ES:[DI],AL ; Write out attribute
- XOR DI,DX ; ...get other plane
- TEST DI,DX ; Done both planes?
- JNZ CG8_06 ; ...skip if not
- ADD DI,50h ; Else position for now char
-
- CG8_06: DEC BH ; Show row of pixels read
- JNZ CG8_04 ; ...not done all of them
- POP SI
- POP DI
- INC DI
- LOOP CG8_03
- POP DS
- RET
-
- CGR_01: CLD ; Increment upwards
- MOV AX,DS:50h ; ...get cursor position
- CALL GRAMAP ; Convert (row,col) -> columns
- MOV SI,AX ; ...save in SI
- SUB SP,8 ; Grab 8 bytes temp storage
- MOV DI,SP ; ...save base in DI
- CMP Byte ptr DS:49h,6 ; Mode 640 x 200 b/w?
- MOV AX,[BP+0] ; ...AX --> CRT regen buffer
- PUSH DS
- PUSH DI
- MOV DS,AX
- JZ CGR_06 ; Mode is 640 x 200 b/w - skip
- MOV DH,8 ; Eight pixels high/char
- SHL SI,1
- MOV BX,2000h ; Bytes per video plane
-
- CGR_02: MOV AX,[SI] ; Read existing word
- XCHG AH,AL
- MOV CX,0C000h ; Attributes to scan for
- MOV DL,0
-
- CGR_03: TEST AX,CX ; Look for attributes
- CLC
- JZ CGR_04 ; ...set, skip
- STC ; Else show not set
-
- CGR_04: RCL DL,1
- SHR CX,1
- SHR CX,1
- JNB CGR_03 ; ...more shifts to go
- MOV SS:[DI],DL
- INC DI
- XOR SI,BX ; Do other video plane
- TEST SI,BX ; ...done both planes?
- JNZ CGR_05 ; ...no, skip
- ADD SI,50h ; Else advance pointer
-
- CGR_05: DEC DH ; Show another pixel row done
- JNZ CGR_02 ; ...more rows to do
- JMP short CGR_08
-
- CGR_06: MOV DH,4 ; Mode 640 x 200 b/w - special
-
- CGR_07: MOV AH,[SI] ; Read pixels from one plane
- MOV SS:[DI],AH ; ...save on stack
- INC DI ; ...advance
- MOV AH,[SI+2000h] ; Read pixels from other plane
- MOV SS:[DI],AH ; Save pixels on stack
- INC DI ; ...advance
- ADD SI,50h ; Total pixels in char
- DEC DH ; ...another row processed
- JNZ CGR_07 ; ...more to do
-
- CGR_08: MOV DX,CS ; Load segment of grafix char
- MOV DI,offset GRAFIX ; ...and offset
- MOV ES,DX ; ...save offset in ES
- MOV DX,SS
- MOV DS,DX
- POP SI
- MOV AL,0
-
- CGR_09: MOV DX,80h ; Number of char. in grafix set
-
- CGR_10: PUSH SI
- PUSH DI
- MOV CX,8 ; Bytes to compare for char
- REPZ CMPSB ; ...do compare
- POP DI
- POP SI
- JZ CGR_11 ; Found grafix character
- INC AL ; ...else show another char
- ADD DI,8 ; ...advance one row
- DEC DX ; ...one less char to scan
- JNZ CGR_10 ; Loop if more char left
-
- OR AL,AL ; User grafix character set?
- JZ CGR_11 ; ...no, not found
- XOR BX,BX
- MOV DS,BX
- LES DI,Dword ptr DS:7Ch ; Else load user grafix char
- MOV BX,ES
- OR BX,DI
- JZ CGR_11 ; ...not found
- JMP short CGR_09 ; Try using user grafix char
-
- CGR_11: MOV [BP+2],AL ; Return char in user AL
- POP DS
- ADD SP,8 ; ...return temp storage
- RET
-
- CRT_11: MOV DX,DS:63h ; Set color, get CGA card port
- ADD DX,5 ; ...color select register
- MOV AL,DS:66h ; Get CRT palette
- MOV AH,[BP+5] ; ...new palette ID, user BH
- OR AH,AH
- MOV AH,[BP+4] ; ...new palette color, user BL
- JNZ C_PAL1 ; Palette ID specified, skip
- AND AL,0E0h
- AND AH,1Fh ; Null ID = ID 01Fh
- OR AL,AH ; ...set in color
- JMP short C_PAL2
-
- C_PAL1: AND AL,0DFh
- TEST AH,1
- JZ C_PAL2
- OR AL,20h
-
- C_PAL2: MOV DS:66h,AL ; Save new palette
- OUT DX,AL ; ...tell CGA about it
- RET
-
- CRT_12: MOV AX,[BP+0] ; Write pixel
- MOV ES,AX
- MOV DX,[BP+8] ; Load row from user DX
- MOV CX,[BP+6] ; ... col from user CX
- CALL LOCDOT ; Find dot offset
- JNZ WD_01 ; ...valid
- MOV AL,[BP+2] ; Load user color
- MOV BL,AL
- AND AL,1
- ROR AL,1
- MOV AH,7Fh
- JMP short WD_02
-
- WD_01: SHL CL,1
- MOV AL,[BP+2]
- MOV BL,AL
- AND AL,3
- ROR AL,1
- ROR AL,1
- MOV AH,3Fh
-
- WD_02: ROR AH,CL
- SHR AL,CL
- MOV CL,ES:[SI] ; Read the char with the dot
- OR BL,BL
- JNS WD_03
- XOR CL,AL ; Exclusive or existing color
- JMP short WD_04
-
- WD_03: AND CL,AH ; Set new color for dot
- OR CL,AL
-
- WD_04: MOV ES:[SI],CL ; Write out char with the dot
- RET
-
- CRT_13: MOV AX,[BP+0] ; AX --> video regen buffer
- MOV ES,AX ; ...into ES segment
- MOV DX,[BP+8] ; Load row from user DX
- MOV CX,[BP+6] ; ... col from user CX
- CALL LOCDOT ; Calculate dot offset
- MOV AL,ES:[SI] ; ...read dot
- JNZ RD_01 ; ...was there
- SHL AL,CL
- ROL AL,1
- AND AL,1
- JMP short RD_02
-
- RD_01: SHL CL,1 ; Calculate offset in char
- SHL AL,CL
- ROL AL,1
- ROL AL,1
- AND AL,3
-
- RD_02: MOV [BP+2],AL ; Return dot pos in user AL
- RET
-
- CRT_14: MOV BL,DS:62h ; Get active video page (0-7)
- SHL BL,1 ; ...as word index
- MOV BH,0 ; ...clear hi order
- MOV DX,[BX+50h] ; Index into cursor position
-
- MOV AL,[BP+2] ; Get char. to write
- CMP AL,8 ; ...back space?
- JZ TTY_BS ; ...skip if so
- CMP AL,LF ; Is it a carriage return
- JZ TTY_LF ; ...skip if so
- CMP AL,7 ; Print a bell?
- JZ BLIP ; ...do beep
- CMP AL,CR ; Is it a line feed?
- JZ TTY_CR ; ...skip if so
- MOV BL,[BP+4] ; Else write at cur pos
- MOV AH,0Ah
- MOV CX,1 ; ...one time
- INT 10h
- INC DL ; Advance cursor
- CMP DL,DS:4Ah ; ...check for line overflow
- JNZ TTYPOS
- MOV DL,0 ; Overflowed, then fake
- JMP short TTY_LF ; ...new line
-
- TTY_BS: CMP DL,0 ; At start of line?
- JZ TTYPOS ; ...skip if so
- DEC DL ; Else back up
- JMP short TTYPOS ; ...join common code
-
- BLIP: MOV BL,2 ; Do a short
- CALL BEEP ; ...beep
- RET
-
- TTY_CR: MOV DL,0 ; Position to start of line
- ; JMP short TTYPOS
-
- TTYPOS: MOV BL,DS:62h ; Get active video page (0-7)
- SHL BL,1 ; ...as word index
- MOV BH,0 ; ...clear hi order
- MOV [BX+50h],DX ; Remember the cursor position
- JMP SETCUR ; ...set 6845 cursor hardware
-
- TTY_LF: CMP DH,18h ; Done all 24 lines on page?
- JZ TTY_L1 ; ...yes, scroll
- INC DH ; Else advance line
- JNZ TTYPOS
-
- TTY_L1: MOV AH,2 ; Position cursor at line start
- INT 10h
- CALL MODCHK ; Is this text mode?
- MOV BH,0
- JB TTY_L2 ; Skip if text mode
- MOV AH,8
- INT 10h ; ...else read attribute
- MOV BH,AH
-
- TTY_L2: MOV AH,6 ; Now prepare to
- MOV AL,1 ; ...scroll
- XOR CX,CX ; ...the
- MOV DH,18h ; ...page
- MOV DL,DS:4Ah ; ...up
- DEC DL
- INT 10h
- RET
-
- CRT_15: MOV AL,DS:4Ah ; Get current video state
- MOV [BP+3],AL ; ...columns
- MOV AL,DS:49h
- MOV [BP+2],AL ; ...mode
- MOV AL,DS:62h
- MOV [BP+5],AL ; ...page
- RET
-
- MODCHK: PUSH AX ; Set flags acc. to cur. mode
- MOV AL,DS:49h ; ...get mode
- CMP AL,7 ; ...EQU if mono
- JZ MODCH1
- CMP AL,4
- CMC
- JNB MODCH1 ; ...carry set on graphix
- SBB AL,AL
- STC
-
- MODCH1: POP AX
- RET
-
- LOCDOT: MOV AL,50h ; Dots in char. position
- XOR SI,SI
- SHR DL,1 ; Two bytes/char. position
- JNB LOCDO1 ; ...not overflow
- MOV SI,2000h ; Else on other video plane
-
- LOCDO1: MUL DL ; Multiply position by row
- ADD SI,AX ; ...add in column position
- MOV DX,CX ; Copy column position
- MOV CX,302h ; ...regular char size
- CMP Byte ptr DS:49h,6 ; Mode 640 x 200, b/w?
- PUSHF
- JNZ LOCDO2 ; ...skip if not
- MOV CX,703h ; Else special char. size
-
- LOCDO2: AND CH,DL
- SHR DX,CL
- ADD SI,DX
- XCHG CL,CH
- POPF
- RET
-
- PENXY: CALL PENXY1 ; Read light pen position HI
- MOV CH,AL ; ...save in CH
- INC AH
- CALL PENXY1 ; Read light pen position LO
- MOV CL,AL ; ...save in CL
- RET
-
- PENXY1: PUSH DX ; Read CRT register offset AL
- MOV DX,DS:63h ; ...get active CRT port
- XCHG AL,AH
- OUT DX,AL ; Send initialization byte
- INC DL ; ...increment
- IN AL,DX ; Read pen position byte back
- POP DX
- RET
-
- MPRC2C: MOV BH,0 ; Convert Row,Col,Page -> Col
- SHL BX,1 ; ...two bytes/column
- MOV AX,[BX+50h] ; Get page number in AX
- ; ...join common code
- RC2COL: PUSH BX ; Map (AH=row,AL=COL) to COL
- MOV BL,AL
- MOV AL,AH
- MUL Byte ptr DS:4Ah ; Multiply ROW x (Row/Column)
- MOV BH,0
- ADD AX,BX ; ...add in existing COL
- SHL AX,1 ; ...times 2 cause 2 bytes/col
- POP BX
- RET
-
- GRAMAP: PUSH BX ; Convert (row,col) -> col
- MOV BL,AL ; ...save column
- MOV AL,AH ; ...get row
- MUL Byte ptr DS:4Ah ; Multiply by columns/row
- SHL AX,1
- SHL AX,1
- MOV BH,0
- ADD AX,BX ; Add in columns
- POP BX
- RET
-
- SETCUR: SHR BL,1 ; Sets 6845 cursor position
- CMP DS:62h,BL ; ...is this page visible?
- JNZ SEND01 ; No, do nothing in hardware
-
- MOVCUR: CALL MPRC2C ; Map row,col,page to col
- ADD AX,DS:4Eh ; + byte offset, regen reg.
- SHR AX,1
- MOV CX,AX
- MOV AH,0Eh ; Tell 6845 video controller
- ; ...to position the cursor
-
- OT6845: MOV AL,CH ; Send CH,CL thru CRT reg AH
- CALL SENDAX ; ...send CH
- INC AH ; ...increment
- MOV AL,CL ; ...send CL
-
- SENDAX: PUSH DX
- MOV DX,DS:63h ; Load active video port
- XCHG AL,AH
- OUT DX,AL ; Send hi order
- XCHG AL,AH
- INC DL
- OUT DX,AL ; ... lo order
- POP DX
-
- SEND01: RET
-
- ENTRY 0F841h ; IBM entry for memory size
-
- INT_12: STI ; Kbytes of memory present
- PUSH DS
- MOV AX,40h
- MOV DS,AX
- MOV AX,DS:13h ; AX = memory size, kilobytes
- POP DS
- IRET
-
- ENTRY 0F84Dh ; IBM entry for equipment check
-
- INT_11: STI ; Equipment present
- PUSH DS
- MOV AX,40h
- MOV DS,AX
- MOV AX,DS:10h ; AX = equipment byte contents
- POP DS
- IRET
-
- ENTRY 0F859h ; IBM entry for cassette int.
-
- INT_15: STC ; Cassette service (error ret)
- MOV AH,86h
- RETF 2
-
- ENTRY 0F85Fh ; IBM non-maskable int. entry
-
- INT_2: PUSH AX ; Non-maskable interrupt
- IN AL,62h
- TEST AL,11000000b ; Get cause of interrupt
- JNZ PAR_01 ; ...parity error
- JMP PAR_07 ; ...math coprocessor (?)
-
- PAR_01: PUSH BX ; Parity error bomb
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH BP
- PUSH DS
- PUSH ES
- MOV AX,40h ; Load data segment
- MOV DS,AX
- CALL V_INIT ; ...clear/init screen
- PUSH DS
- PUSH CS ; Point DS at ROM
- POP DS
- MOV SI,offset BOMB_1 ; SI --> Parity message
- CALL PRINT ; ...print
- POP DS ; ...restore DS
- MOV AX,11h ; Back cursor over ? marks
- CALL LOCATE ; ...with call
- MOV AL,0
- OUT 0A0h,AL ; ...disable NMI interrupts
- MOV DX,61h
- IN AL,DX ; Get machine flags
- OR AL,00110000b ; ...disable parity int.
- OUT DX,AL ; Put out new flags
- AND AL,11001111b ; ...enable parity int.
- OUT DX,AL ; Put out new flags
- MOV CL,6
- MOV BX,DS:13h ; Get memory size (K bytes)
- SHL BX,CL
- INC DX ; ...now paragraphs
- XOR AX,AX
- MOV DS,AX
-
- PAR_02: MOV CX,10h ; Iterations to check
- XOR SI,SI
-
- PAR_03: MOV AH,[SI] ; Read the byte (dummy)
- IN AL,DX ; ...and read status
- TEST AL,11000000b ; ...to see what happened
- JNZ PAR_04 ; Read caused parity error
- INC SI ; ...else advance pointer
- LOOP PAR_03 ; ...and try next byte
-
- MOV AX,DS
- INC AX ; ...next paragraph
- MOV DS,AX
- CMP AX,BX
- JNZ PAR_02 ; More paragraphs to check
- JMP short PAR_05 ; ...else flakey error
-
- PAR_04: MOV [SI],AH ; Save offset in paragraph
- MOV AX,DS
- CALL BIGNUM ; Print segment
- MOV AX,SI
- CALL DIGIT ; Print offset
-
- PAR_05: MOV AX,16h ; Where to position cursor
- CALL LOCATE ; ...position cursor
- PUSH DS
- PUSH CS
- POP DS
- MOV SI,offset BOMB_2 ; Continue ?
- CALL PRINT ; ...ask the user
- POP DS
- IN AL,21h ; Get interrupt masks
- PUSH AX ; ...save them
- MOV AL,11111100b
- OUT 21h,AL ; Disable all but keyboard
- STI ; ...enable interrupt system
- CALL GETCH ; Get keyboard character
- PUSH AX ; ...save it
- CALL OUTCHR ; Print ascii character
- POP AX ; ...restore
- CMP AL,'Y' ; User wants to continue
- JZ PAR_06 ; ...stupid answer
- CMP AL,'y' ; Look for little case "y"
- JZ PAR_06 ; ...stupid answer
- JMP COLD ; Retry on cold reboot
-
- PAR_06: CALL BLANK ; Clear display
- POP AX
- OUT 21h,AL ; Restore interrupt system state
- MOV DX,61h ; Dismiss the NMI interrupt
- IN AL,DX ; ...read in machine flags
- OR AL,00110000b
- OUT DX,AL ; Write out, parity disabled
- AND AL,11001111b ; ...clears parity error
- OUT DX,AL ; Write out, parity enabled
- MOV AL,80h
- OUT 0A0h,AL ; Enable NMI interrupts
- POP ES
- POP DS
- POP BP
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
-
- PAR_07: POP AX
- IRET
-
- BOMB_1 db 'Parity error at: ?????',0
- BOMB_2 db ' Cont?',0
-
- NUMBER: PUSH AX ; Save number
- MOV CL,4
- SHR AL,CL
- CALL DIGIT ; Out first digit
- POP AX
- CALL DIGIT ; Out second digit
- RET
-
- BIGNUM: PUSH AX ; Unsigned word
- MOV AL,AH
- CALL NUMBER
- POP AX
- CALL NUMBER
- RET
-
- OUTCHR: PUSH BX
- PUSH AX
- MOV AH,0Eh ; Teletype print service
- MOV BL,7 ; ...normal intensity
- INT 10h
- POP AX
- POP BX
- RET
-
- DIGIT: PUSH AX ; Print hex digit in AL
- AND AL,0Fh
- CMP AL,9
- JBE D_01
- ADD AL,'A'-'9'-1
-
- D_01: ADD AL,'0' ; Make ascii digit
- CALL OUTCHR ; ...print it
- POP AX
- RET
-
- MOV AL,CR ; Print carriage return
- CALL OUTCHR ; ...on screen
- MOV AL,LF ; Print line feed
- CALL OUTCHR ; ...on screen
- RET
-
- GETCH: MOV AH,0 ; Read keyboard key
- INT 16h
- RET
-
- PRINT: LODSB ; Print zero terminated string
- OR AL,AL
- JNZ PRINT1 ; ...not terminator in AX
- RET
-
- PRINT1: CALL OUTCHR ; Print character in AX
- JMP PRINT ; ...back for more
-
- BEEP: PUSH AX
- PUSH CX
- MOV AL,10110110b ; Timer ic 8253 square waves
- OUT 43h,AL ; ...channel 2, speaker
- MOV AX,528h ; Get countdown constant word
- OUT 42h,AL ; ...send lo order
- MOV AL,AH ; ...load hi order
- OUT 42h,AL ; ...send hi order
- IN AL,61h ; Read ic 8255 machine status
- PUSH AX
- OR AL,00000011b
- OUT 61h,AL ; Turn speaker on
- XOR CX,CX
-
- BEEP_1: LOOP BEEP_1
- DEC BL
- JNZ BEEP_1
- POP AX
- OUT 61h,AL ; Turn speaker off
- POP CX
- POP AX
- RET
-
- V_INIT: MOV AH,DS:10h ; Get equipment byte
- AND AH,00110000b ; ...extract CRT
- MOV AL,0 ; ...null lo
- CMP AH,00110000b ; Monochrome?
- JZ LF9D9 ; ...yes
- MOV AL,1 ; CGA 40 x 25?
- CMP AH,00010000b ; ...yes
- JZ LF9D9 ; CGA 80 x 25?
- MOV AL,3 ; ...yes
-
- LF9D9: MOV AH,0 ; Setup subfunction
- INT 10h ; ...to video
- RET
-
- BLANK: MOV DX,184Fh ; Lower right corner of scroll
- XOR CX,CX ; Upper left corner of scroll
- MOV AX,600h ; Blank entire window
- MOV BH,7 ; Set regular cursor
- INT 10h ; Call video service scroll
- MOV AH,2 ; Set cursor position
- XOR DX,DX ; ...upper left corner
- MOV BH,0 ; ...page 0
- INT 10h ; ...call video service
- RET
-
- LOCATE: PUSH DX
- PUSH BX
- MOV DX,AX ; Get position for cursor
- MOV AH,2
- MOV BH,0 ; ...page 0
- INT 10h
- POP BX
- POP DX
- RET
-
- CHKSUM: MOV CX,2000h ; Bytes in 2764 eprom
-
- CHK_01: MOV AL,0 ; ...zero checksum
-
- ADDBYT: ADD AL,[BX] ; Add byte to checksum
- INC BX ; ...BX --> next byte
- LOOP ADDBYT ; ...loop until done
- OR AL,AL ; Set condition codes
- RET ; ...and return
-
- MEMTST: MOV BX,0400h ; Load bytes to test
- MOV AL,55h
- ;
- PAT_1: XOR DI,DI ; Pattern #1, 55h bytes
- MOV CX,BX
- REPZ STOSB ; Fill memory, pattern #1
- XOR DI,DI
- MOV CX,BX
- REPZ SCASB ; Scan memory for NOT pattern #1
- JCXZ PAT_2
- STC ; ...flunked
- RET
-
- PAT_2: XOR DI,DI ; Pattern #2 - 0AAh bytes
- MOV CX,BX
- NOT AL
- REPZ STOSB ; Fill memory, pattern #2
- XOR DI,DI
- MOV CX,BX
- REPZ SCASB ; Scan memory for NOT pattern #2
- JCXZ PAT_3
- STC ; ...flunked
- RET
-
- PAT_3: XOR DI,DI ; Pattern #3 - 01h bytes
- MOV CX,BX
- MOV AL,1
- REPZ STOSB ; Fill memory, pattern #3
- XOR DI,DI
- MOV CX,BX
- REPZ SCASB ; Scan memory for NOT pattern #3
- JCXZ PAT_4
- STC ; ...flunked
- RET
-
- PAT_4: XOR DI,DI ; Pattern #4 - 0h bytes
- MOV CX,BX
- DEC AL
- REPZ STOSB ; Fill memory, pattern #4
- XOR DI,DI
- MOV CX,BX
- REPZ SCASB ; Scan memory for NOT pattern #4
- JCXZ LFA59
- STC ; ...flunked
- RET
-
- LFA59: MOV AX,ES
- ADD AX,40h ; Add 40h to segment number
- MOV ES,AX
- RET ; ...passed
-
- ENTRY 0FA6Eh ; IBM graphics char set entry
-
- GRAFIX db 000h,000h,000h,000h ; Graphics character set
- db 000h,000h,000h,000h
- db 07Eh,081h,0A5h,081h
- db 0BDh,099h,081h,07Eh
- db 07Eh,0FFh,0DBh,0FFh
- db 0C3h,0E7h,0FFh,07Eh
- db 06Ch,0FEh,0FEh,0FEh
- db 07Ch,038h,010h,000h
-
- db 010h,038h,07Ch,0FEh
- db 07Ch,038h,010h,000h
- db 038h,07Ch,038h,0FEh
- db 0FEh,07Ch,038h,07Ch
- db 010h,010h,038h,07Ch
- db 0FEh,07Ch,038h,07Ch
- db 000h,000h,018h,03Ch
- db 03Ch,018h,000h,000h
-
- db 0FFh,0FFh,0E7h,0C3h
- db 0C3h,0E7h,0FFh,0FFh
- db 000h,03Ch,066h,042h
- db 042h,066h,03Ch,000h
- db 0FFh,0C3h,099h,0BDh
- db 0BDh,099h,0C3h,0FFh
- db 00Fh,007h,00Fh,07Dh
- db 0CCh,0CCh,0CCh,078h
-
- db 03Ch,066h,066h,066h
- db 03Ch,018h,07Eh,018h
- db 03Fh,033h,03Fh,030h
- db 030h,070h,0F0h,0E0h
- db 07Fh,063h,07Fh,063h
- db 063h,067h,0E6h,0C0h
- db 099h,05Ah,03Ch,0E7h
- db 0E7h,03Ch,05Ah,099h
-
- db 080h,0E0h,0F8h,0FEh
- db 0F8h,0E0h,080h,000h
- db 002h,00Eh,03Eh,0FEh
- db 03Eh,00Eh,002h,000h
- db 018h,03Ch,07Eh,018h
- db 018h,07Eh,03Ch,018h
- db 066h,066h,066h,066h
- db 066h,000h,066h,000h
-
- db 07Fh,0DBh,0DBh,07Bh
- db 01Bh,01Bh,01Bh,000h
- db 03Eh,063h,038h,06Ch
- db 06Ch,038h,0CCh,078h
- db 000h,000h,000h,000h
- db 07Eh,07Eh,07Eh,000h
- db 018h,03Ch,07Eh,018h
- db 07Eh,03Ch,018h,0FFh
-
- db 018h,03Ch,07Eh,018h
- db 018h,018h,018h,000h
- db 018h,018h,018h,018h
- db 07Eh,03Ch,018h,000h
- db 000h,018h,00Ch,0FEh
- db 00Ch,018h,000h,000h
- db 000h,030h,060h,0FEh
- db 060h,030h,000h,000h
-
- db 000h,000h,0C0h,0C0h
- db 0C0h,0FEh,000h,000h
- db 000h,024h,066h,0FFh
- db 066h,024h,000h,000h
- db 000h,018h,03Ch,07Eh
- db 0FFh,0FFh,000h,000h
- db 000h,0FFh,0FFh,07Eh
- db 03Ch,018h,000h,000h
-
- db 000h,000h,000h,000h
- db 000h,000h,000h,000h
- db 030h,078h,078h,030h
- db 030h,000h,030h,000h
- db 06Ch,06Ch,06Ch,000h
- db 000h,000h,000h,000h
- db 06Ch,06Ch,0FEh,06Ch
- db 0FEh,06Ch,06Ch,000h
-
- db 030h,07Ch,0C0h,078h
- db 00Ch,0F8h,030h,000h
- db 000h,0C6h,0CCh,018h
- db 030h,066h,0C6h,000h
- db 038h,06Ch,038h,076h
- db 0DCh,0CCh,076h,000h
- db 060h,060h,0C0h,000h
- db 000h,000h,000h,000h
-
- db 018h,030h,060h,060h
- db 060h,030h,018h,000h
- db 060h,030h,018h,018h
- db 018h,030h,060h,000h
- db 000h,066h,03Ch,0FFh
- db 03Ch,066h,000h,000h
- db 000h,030h,030h,0FCh
- db 030h,030h,000h,000h
-
- db 000h,000h,000h,000h
- db 000h,030h,030h,060h
- db 000h,000h,000h,0FCh
- db 000h,000h,000h,000h
- db 000h,000h,000h,000h
- db 000h,030h,030h,000h
- db 006h,00Ch,018h,030h
- db 060h,0C0h,080h,000h
-
- db 07Ch,0C6h,0CEh,0DEh
- db 0F6h,0E6h,07Ch,000h
- db 030h,070h,030h,030h
- db 030h,030h,0FCh,000h
- db 078h,0CCh,00Ch,038h
- db 060h,0CCh,0FCh,000h
- db 078h,0CCh,00Ch,038h
- db 00Ch,0CCh,078h,000h
-
- db 01Ch,03Ch,06Ch,0CCh
- db 0FEh,00Ch,01Eh,000h
- db 0FCh,0C0h,0F8h,00Ch
- db 00Ch,0CCh,078h,000h
- db 038h,060h,0C0h,0F8h
- db 0CCh,0CCh,078h,000h
- db 0FCh,0CCh,00Ch,018h
- db 030h,030h,030h,000h
-
- db 078h,0CCh,0CCh,078h
- db 0CCh,0CCh,078h,000h
- db 078h,0CCh,0CCh,07Ch
- db 00Ch,018h,070h,000h
- db 000h,030h,030h,000h
- db 000h,030h,030h,000h
- db 000h,030h,030h,000h
- db 000h,030h,030h,060h
-
- db 018h,030h,060h,0C0h
- db 060h,030h,018h,000h
- db 000h,000h,0FCh,000h
- db 000h,0FCh,000h,000h
- db 060h,030h,018h,00Ch
- db 018h,030h,060h,000h
- db 078h,0CCh,00Ch,018h
- db 030h,000h,030h,000h
-
- db 07Ch,0C6h,0DEh,0DEh
- db 0DEh,0C0h,078h,000h
- db 030h,078h,0CCh,0CCh
- db 0FCh,0CCh,0CCh,000h
- db 0FCh,066h,066h,07Ch
- db 066h,066h,0FCh,000h
- db 03Ch,066h,0C0h,0C0h
- db 0C0h,066h,03Ch,000h
-
- db 0F8h,06Ch,066h,066h
- db 066h,06Ch,0F8h,000h
- db 0FEh,062h,068h,078h
- db 068h,062h,0FEh,000h
- db 0FEh,062h,068h,078h
- db 068h,060h,0F0h,000h
- db 03Ch,066h,0C0h,0C0h
- db 0CEh,066h,03Eh,000h
-
- db 0CCh,0CCh,0CCh,0FCh
- db 0CCh,0CCh,0CCh,000h
- db 078h,030h,030h,030h
- db 030h,030h,078h,000h
- db 01Eh,00Ch,00Ch,00Ch
- db 0CCh,0CCh,078h,000h
- db 0E6h,066h,06Ch,078h
- db 06Ch,066h,0E6h,000h
-
- db 0F0h,060h,060h,060h
- db 062h,066h,0FEh,000h
- db 0C6h,0EEh,0FEh,0FEh
- db 0D6h,0C6h,0C6h,000h
- db 0C6h,0E6h,0F6h,0DEh
- db 0CEh,0C6h,0C6h,000h
- db 038h,06Ch,0C6h,0C6h
- db 0C6h,06Ch,038h,000h
-
- db 0FCh,066h,066h,07Ch
- db 060h,060h,0F0h,000h
- db 078h,0CCh,0CCh,0CCh
- db 0DCh,078h,01Ch,000h
- db 0FCh,066h,066h,07Ch
- db 06Ch,066h,0E6h,000h
- db 078h,0CCh,0E0h,070h
- db 01Ch,0CCh,078h,000h
-
- db 0FCh,0B4h,030h,030h
- db 030h,030h,078h,000h
- db 0CCh,0CCh,0CCh,0CCh
- db 0CCh,0CCh,0FCh,000h
- db 0CCh,0CCh,0CCh,0CCh
- db 0CCH,078h,030h,000h
- db 0C6h,0C6h,0C6h,0D6h
- db 0FEh,0EEh,0C6h,000h
-
- db 0C6h,0C6h,06Ch,038h
- db 038h,06Ch,0C6h,000h
- db 0CCh,0CCh,0CCh,078h
- db 030h,030h,078h,000h
- db 0FEh,0C6h,08Ch,018h
- db 032h,066h,0FEh,000h
- db 078h,060h,060h,060h
- db 060h,060h,078h,000h
-
- db 0C0h,060h,030h,018h
- db 00Ch,006h,002h,000h
- db 078h,018h,018h,018h
- db 018h,018h,078h,000h
- db 010h,038h,06Ch,0C6h
- db 000h,000h,000h,000h
- db 000h,000h,000h,000h
- db 000h,000h,000h,0FFh
-
- db 030h,030h,018h,000h
- db 000h,000h,000h,000h
- db 000h,000h,078h,00Ch
- db 07Ch,0CCh,076h,000h
- db 0E0h,060h,060h,07Ch
- db 066h,066h,0DCh,000h
- db 000h,000h,078h,0CCh
- db 0C0h,0CCh,078h,000h
-
- db 01Ch,00Ch,00Ch,07Ch
- db 0CCh,0CCh,076h,000h
- db 000h,000h,078h,0CCh
- db 0FCh,0C0h,078h,000h
- db 038h,06Ch,060h,0F0h
- db 060h,060h,0F0h,000h
- db 000h,000h,076h,0CCh
- db 0CCh,07Ch,00Ch,0F8h
-
- db 0E0h,060h,06Ch,076h
- db 066h,066h,0E6h,000h
- db 030h,000h,070h,030h
- db 030h,030h,078h,000h
- db 00Ch,000h,00Ch,00Ch
- db 00Ch,0CCh,0CCh,078h
- db 0E0h,060h,066h,06Ch
- db 078h,06Ch,0E6h,000h
-
- db 070h,030h,030h,030h
- db 030h,030h,078h,000h
- db 000h,000h,0CCh,0FEh
- db 0FEh,0D6h,0C6h,000h
- db 000h,000h,0F8h,0CCh
- db 0CCh,0CCh,0CCh,000h
- db 000h,000h,078h,0CCh
- db 0CCh,0CCh,078h,000h
-
- db 000h,000h,0DCh,066h
- db 066h,07Ch,060h,0F0h
- db 000h,000h,076h,0CCh
- db 0CCh,07Ch,00Ch,01Eh
- db 000h,000h,0DCh,076h
- db 066h,060h,0F0h,000h
- db 000h,000h,07Ch,0C0h
- db 078h,00Ch,0F8h,000h
-
- db 010h,030h,07Ch,030h
- db 030h,034h,018h,000h
- db 000h,000h,0CCh,0CCh
- db 0CCh,0CCh,076h,000h
- db 000h,000h,0CCh,0CCh
- db 0CCh,078h,030h,000h
- db 000h,000h,0C6h,0D6h
- db 0FEh,0FEh,06Ch,000h
-
- db 000h,000h,0C6h,06Ch
- db 038h,06Ch,0C6h,000h
- db 000h,000h,0CCh,0CCh
- db 0CCh,07Ch,00Ch,0F8h
- db 000h,000h,0FCh,098h
- db 030h,064h,0FCh,000h
- db 01Ch,030h,030h,0E0h
- db 030h,030h,01Ch,000h
-
- db 018h,018h,018h,000h
- db 018h,018h,018h,000h
- db 0E0h,030h,030h,01Ch
- db 030h,030h,0E0h,000h
- db 076h,0DCh,000h,000h
- db 000h,000h,000h,000h
- db 000h,010h,038h,06Ch
- db 0C6h,0C6h,0FEh,000h
-
- ENTRY 0FE6Eh ; IBM entry, time_of_day clock
-
- INT_1A: STI ; User time_of_day bios service
- PUSH DS
- PUSH AX
- MOV AX,40h
- MOV DS,AX
- POP AX ; Get request type
- CLI ; ...freeze clock
- OR AH,AH
- JZ TD_01 ; Read time, AH=0
- DEC AH
- JNZ TD_02 ; ...invalid request
- MOV DS:6Ch,DX ; Set time, AH=1
- MOV DS:6Eh,CX ; ...set time hi
- MOV Byte ptr DS:70h,0 ; ...not a new day
- JMP short TD_02
-
- TD_01: MOV CX,DS:6Eh ; Read lo order time
- MOV DX,DS:6Ch ; ... hi order time
- CALL TD_03 ; Read resets overflow
-
- TD_02: STI ; Unfreeze clock
- POP DS
- IRET
-
- TD_03: MOV AL,DS:70h ; Zero the overflow and return
- XOR DS:70h,AL ; ...previous status in flags
- RET
-
- ENTRY 0FEA5h ; IBM entry, hardware clock
-
- INT_8: STI ; Routine services clock tick
- PUSH DS
- PUSH DX
- PUSH AX
- MOV AX,40h
- MOV DS,AX
- DEC Byte ptr DS:40h ; Decrement motor count
- JNZ TI_01 ; ...not time to shut off
- AND Byte ptr DS:3Fh,11110000b ; Else show motor off
- MOV AL,0Ch ; ...send motor off
- MOV DX,3F2h ; ...to the floppy
- OUT DX,AL ; ...disk controller
-
- TI_01: INC Word ptr DS:6Ch ; Bump lo order time of day
- JNZ TI_02 ; ...no carry
- INC Word ptr DS:6Eh ; Bump hi order time of day
-
- TI_02: CMP Word ptr DS:6Eh,18h ; Is it midnight yet?
- JNZ TI_03 ; ...no
- CMP Word ptr DS:6Ch,0B0h ; Possibly, check lo order
- JNZ TI_03 ; ...not midnight
- MOV Word ptr DS:6Eh,0 ; Midnight, reset hi order
- MOV Word ptr DS:6Ch,0 ; ...lo order ticks
- MOV Byte ptr DS:70h,1 ; Show new day since last read
-
- TI_03: INT 1Ch ; Execute user clock service
- MOV AL,20h ; ...send end_of_interrupt
- OUT 20h,AL ; ...to 8259 interrupt chip
- POP AX
- POP DX
- POP DS
- IRET
-
- ENTRY 0FEF3h ; IBM entry, time_of_day clock
-
- VECTORS dw int_8 ; Timer tick
- dw int_9 ; Key attention
- dw IGNORE ; Reserved
- dw IGNORE ; Reserved for COM2 serial i/o
- dw IGNORE ; Reserved for COM1 serial i/o
- dw IGNORE ; Reserved for hard disk attn.
- dw int_e ; Floppy disk attention
- dw IGNORE ; Reserved for parallel printer
- dw int_10 ; Video bios services
- dw int_11 ; Equipment present
- dw int_12 ; Memories present
- dw int_13 ; Disk bios services
- dw int_14 ; Serial com. services
- dw int_15 ; Cassette bios services
- dw int_16 ; Keyboard bios services
- dw int_17 ; Parallel printer services
- dw IGNORE ; rom Basic (setup later)
- dw int_19 ; Bootstrap
- dw int_1a ; Timer bios services
- dw DUMMY ; Keyboard break user service
- dw DUMMY ; System tick user service
- dw int_1d ; Video parameter table
- dw int_1e ; Disk parameter table
- dw ? ; Graphic charactr table ptr
-
- ENTRY 0FF23h ; IBM entry, nonsense interrupt
-
- IGNORE: PUSH DS ; Unexpected interrupts go here
- PUSH DX
- PUSH AX
- MOV AX,40h
- MOV DS,AX
- MOV AL,0Bh ; What IRQ caused this?
- OUT 20h,AL
- NOP
- IN AL,20h ; ...(read IRQ level)
- MOV AH,AL
- OR AL,AL
- JNZ DU_1
- MOV AL,0FFh ; Not hardware, say 0FFh IRQ
- JMP short DU_2
-
- DU_1: IN AL,21h ; Clear the IRQ
- OR AL,AH
- OUT 21h,AL
- MOV AL,20h ; Send end_of_interrupt code
- OUT 20h,AL ; ...to 8259 interrupt chip
-
- DU_2: MOV DS:6Bh,AH ; Save last nonsense interrupt
- POP AX
- POP DX
- POP DS
- IRET
-
- ENTRY 0FF53h ; IBM entry, dummy interrupts
-
- ;INT_1B: ; Keyboard break user service
- ;INT_1C: ; Clock tick user service
- DUMMY: IRET
-
- ENTRY 0FF54h ; IBM entry, print screen
-
- INT_5: STI ; Print screen service
- PUSH DS
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- MOV AX,40h
- MOV DS,AX
- CMP Byte ptr DS:100h,1 ; Print screen in progress?
- JZ PS_5 ; ...yes, ignore
- MOV Byte ptr DS:100h,1 ; Flag print screen in progress
- CALL P_CRLF ; ...begin new line
- MOV AH,0Fh
- INT 10h ; Get current video state
- PUSH AX ; ...save it
- MOV AH,3
- INT 10h ; Read cursor position
- POP AX ; ...retrieve video state
- PUSH DX ; ...save cursor position
- MOV CH,19h ; Do 25 rows
- MOV CL,AH ; ...columns in current mode
- XOR DX,DX ; Start printing from (0,0)
-
- PS_1: MOV AH,2 ; Set cursor to position
- INT 10h
- MOV AH,8 ; ...and read character
- INT 10h
- OR AL,AL ; Nulls are special case
- JNZ PS_2
- MOV AL,' ' ; ...convert to spaces
-
- PS_2: PUSH DX
- XOR DX,DX
- MOV AH,DL ; Function=Print character
- INT 17h
- POP DX
- TEST AH,00100101b ; Successful print
- JZ PS_3
- MOV Byte ptr DS:100h,0FFh ; No, error in Print Screen
- JMP short PS_4
-
- PS_3: INC DL ; Increment column count
- CMP CL,DL
- JNZ PS_1 ; ...in range, continue
- MOV DL,0
- CALL P_CRLF ; Else print new line
- INC DH ; ...add another row
- CMP DH,CH ; Done all 25 rows?
- JNZ PS_1 ; ...no, continue
- MOV Byte ptr DS:100h,0 ; Show done Print Screen OK
-
- PS_4: POP DX ; Get saved cursor position
- MOV AH,2
- INT 10h ; ...restore it
-
- PS_5: POP DX
- POP CX
- POP BX
- POP AX
- POP DS
- IRET
-
- ENTRY 0FFCBh ; IBM entry, display CR, LF
-
- P_CRLF: PUSH DX ; Print CR, LF, on line printer
- XOR DX,DX
- MOV AH,DL ; Function=print
- MOV AL,LF ; LF
- INT 17h
- MOV AH,0
- MOV AL,CR ; CR
- INT 17h
- POP DX
- RET
-
- ;******************************************************************************
- ENTRY 0FFF0h ; Hardware power reset entry *
- PUBLIC POWER ; ...ic "8088" or "V20" *
- POWER: JMPF 0F000h,COLD ; ...begins here on power up *
- ;******************************************************************************
-
- ENTRY 0FFF5h ; Release date, Yankee style
- db "08/23/87" ; ...MM/DD/YY (not logical)
-
- ENTRY 0FFFEh
- db 0FEh ; Computer type (XT)
- ; db ? ; Checksum byte
- code ENDS
- ;
- END
-